[ci] update smoke tests (remote) (#2686)
Co-authored-by: FredKSchott <FredKSchott@users.noreply.github.com> Co-authored-by: Fred K. Schott <fkschott@gmail.com>
|
@ -4,14 +4,20 @@
|
|||
"private": true,
|
||||
"scripts": {
|
||||
"start": "astro dev --experimental-static-build",
|
||||
"dev": "astro dev",
|
||||
"dev": "astro dev --experimental-static-build",
|
||||
"debug": "DEBUG=* astro dev --experimental-static-build",
|
||||
"build": "astro build --experimental-static-build",
|
||||
"preview": "astro preview",
|
||||
"update-contributors": "node ./update-contributors.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"astro": "0.23.0-next.10",
|
||||
"astro-icon": "^0.6.0"
|
||||
"@tailwindcss/aspect-ratio": "^0.4.0",
|
||||
"@tailwindcss/typography": "^0.5.2",
|
||||
"astro": "0.23.3",
|
||||
"astro-icon": "^0.6.0",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"postcss": "^8.4.7",
|
||||
"tailwindcss": "^3.0.23"
|
||||
},
|
||||
"volta": {
|
||||
"node": "14.18.3"
|
||||
|
@ -19,7 +25,7 @@
|
|||
"dependencies": {
|
||||
"date-fns": "^2.28.0",
|
||||
"quicklink": "^2.2.0",
|
||||
"rehype-autolink-headings": "^6.1.0",
|
||||
"rehype-autolink-headings": "^6.1.1",
|
||||
"remark-autolink-headings": "^7.0.1",
|
||||
"remark-smartypants": "^2.0.0",
|
||||
"smartypants": "^0.1.6"
|
||||
|
|
4109
smoke/astro.build-main/pnpm-lock.yaml
Normal file
10
smoke/astro.build-main/postcss.config.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {
|
||||
config: path.join(__dirname, 'tailwind.config.js'), // update this if your path differs!
|
||||
},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
BIN
smoke/astro.build-main/public/assets/press/full-logo-dark.png
Normal file
After Width: | Height: | Size: 23 KiB |
|
@ -0,0 +1,9 @@
|
|||
<svg width="2712" height="894" viewBox="0 0 2712 894" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M445.432 22.9832C452.722 32.0324 456.439 44.2432 463.873 68.6647L626.28 602.176C566.233 571.026 500.957 548.56 432.114 536.439L326.37 179.099C324.64 173.252 319.27 169.241 313.173 169.241C307.06 169.241 301.679 173.273 299.963 179.14L195.5 536.259C126.337 548.325 60.7627 570.832 0.458984 602.095L163.664 68.5412C171.121 44.1617 174.85 31.9718 182.139 22.9393C188.575 14.9651 196.946 8.77213 206.453 4.95048C217.223 0.621582 229.97 0.621582 255.465 0.621582H372.034C397.562 0.621582 410.326 0.621582 421.106 4.95951C430.622 8.78908 438.998 14.9946 445.432 22.9832Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M464.866 627.566C438.093 650.46 384.655 666.073 323.1 666.073C247.551 666.073 184.228 642.553 167.425 610.921C161.418 629.05 160.071 649.798 160.071 663.052C160.071 663.052 156.114 728.134 201.38 773.401C201.38 749.896 220.434 730.842 243.938 730.842C284.225 730.842 284.18 765.99 284.143 794.506C284.142 795.36 284.141 796.209 284.141 797.051C284.141 840.333 310.594 877.436 348.215 893.075C342.596 881.518 339.444 868.54 339.444 854.825C339.444 813.545 363.678 798.175 391.844 780.311C414.254 766.098 439.154 750.307 456.314 718.629C465.268 702.101 470.352 683.17 470.352 663.052C470.352 650.68 468.429 638.757 464.866 627.566Z" fill="#FF5D01"/>
|
||||
<path d="M999.147 593.833C1067.08 593.833 1118.03 569.665 1138.93 528.516C1138.93 548.111 1140.23 568.36 1143.5 584.036H1255.19C1249.97 561.173 1247.35 529.82 1247.35 488.671V388.081C1247.35 292.717 1191.18 247.648 1066.42 247.648C957.344 247.648 884.188 292.717 875.696 366.527H991.962C995.881 334.521 1022.66 316.885 1066.42 316.885C1109.53 316.885 1133.7 334.521 1133.7 371.1V380.896L1015.48 391.347C957.997 397.227 925.338 407.023 902.476 422.7C878.309 439.028 865.898 463.851 865.898 494.549C865.898 555.948 916.847 593.833 999.147 593.833ZM1042.26 525.902C1004.37 525.902 981.511 510.88 981.511 486.712C981.511 461.892 1000.45 448.827 1048.14 442.949L1135.66 433.805V453.4C1135.66 497.163 1097.78 525.902 1042.26 525.902Z" fill="white"/>
|
||||
<path d="M1490.77 593.833C1604.42 593.833 1662.56 551.377 1662.56 482.793C1662.56 425.966 1629.9 394.613 1550.87 384.162L1452.23 373.059C1424.15 369.138 1412.39 361.953 1412.39 346.277C1412.39 327.336 1431.33 318.844 1474.44 318.844C1533.88 318.844 1575.03 332.561 1608.35 359.342L1661.25 306.434C1624.67 268.55 1561.32 247.648 1482.93 247.648C1372.55 247.648 1311.15 286.838 1311.15 352.809C1311.15 410.289 1349.03 442.295 1427.41 452.745L1516.25 463.196C1551.52 467.769 1561.97 474.302 1561.97 491.283C1561.97 510.88 1542.37 521.331 1496.65 521.331C1428.72 521.331 1383 503.041 1352.3 469.076L1292.2 518.717C1332.05 568.36 1399.98 593.833 1490.77 593.833Z" fill="white"/>
|
||||
<path d="M1754.78 331.255V469.076C1754.78 550.07 1800.5 591.221 1898.48 591.221C1928.53 591.221 1952.04 587.955 1974.25 581.423V496.508C1962.49 499.122 1948.12 501.734 1929.18 501.734C1888.03 501.734 1867.78 483.446 1867.78 444.908V331.255H1974.9V257.445H1867.78V137.914L1754.78 179.717V257.445H1681.62V331.255H1754.78Z" fill="white"/>
|
||||
<path d="M2137.13 257.445H2033.93V584.036H2146.93V461.892C2146.93 426.618 2154.77 394.613 2176.33 374.364C2193.31 358.687 2217.48 350.198 2251.44 350.198C2263.85 350.198 2273.65 351.502 2284.75 352.809V250.26C2277.57 248.954 2272.34 248.954 2263.2 248.954C2198.53 248.954 2154.77 286.185 2137.13 346.932V257.445Z" fill="white"/>
|
||||
<path d="M2508.05 593.833C2627.59 593.833 2711.85 530.475 2711.85 420.088C2711.85 310.353 2627.59 247.648 2508.05 247.648C2387.87 247.648 2303.61 310.353 2303.61 420.088C2303.61 530.475 2387.87 593.833 2508.05 593.833ZM2508.05 518.717C2453.19 518.717 2418.57 483.446 2418.57 420.088C2418.57 356.728 2453.19 322.763 2508.05 322.763C2562.27 322.763 2596.89 356.728 2596.89 420.088C2596.89 483.446 2562.27 518.717 2508.05 518.717Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
BIN
smoke/astro.build-main/public/assets/press/full-logo-light.png
Normal file
After Width: | Height: | Size: 22 KiB |
|
@ -0,0 +1,9 @@
|
|||
<svg width="2712" height="894" viewBox="0 0 2712 894" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M445.433 22.9832C452.722 32.0324 456.439 44.2432 463.873 68.6647L626.281 602.176C566.234 571.026 500.957 548.56 432.115 536.439L326.371 179.099C324.641 173.252 319.27 169.241 313.173 169.241C307.06 169.241 301.68 173.273 299.963 179.14L195.5 536.259C126.338 548.325 60.7632 570.832 0.459473 602.095L163.664 68.5412C171.121 44.1617 174.85 31.9718 182.14 22.9393C188.575 14.9651 196.946 8.77213 206.454 4.95048C217.224 0.621582 229.971 0.621582 255.466 0.621582H372.034C397.562 0.621582 410.326 0.621582 421.106 4.95951C430.622 8.78908 438.998 14.9946 445.433 22.9832Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M464.867 627.566C438.094 650.46 384.655 666.073 323.101 666.073C247.551 666.073 184.229 642.553 167.426 610.921C161.419 629.05 160.072 649.798 160.072 663.052C160.072 663.052 156.114 728.134 201.38 773.401C201.38 749.896 220.435 730.842 243.939 730.842C284.226 730.842 284.181 765.99 284.144 794.506C284.143 795.36 284.142 796.209 284.142 797.051C284.142 840.333 310.595 877.436 348.215 893.075C342.596 881.518 339.444 868.54 339.444 854.825C339.444 813.545 363.679 798.175 391.845 780.311C414.255 766.098 439.155 750.307 456.315 718.629C465.268 702.101 470.352 683.17 470.352 663.052C470.352 650.68 468.43 638.757 464.867 627.566Z" fill="#FF5D01"/>
|
||||
<path d="M999.148 593.833C1067.08 593.833 1118.03 569.665 1138.93 528.516C1138.93 548.111 1140.23 568.36 1143.5 584.036H1255.19C1249.97 561.173 1247.36 529.82 1247.36 488.671V388.081C1247.36 292.717 1191.18 247.648 1066.43 247.648C957.344 247.648 884.188 292.717 875.697 366.527H991.963C995.882 334.521 1022.66 316.885 1066.43 316.885C1109.53 316.885 1133.7 334.521 1133.7 371.1V380.896L1015.48 391.347C957.997 397.227 925.338 407.023 902.477 422.7C878.31 439.028 865.899 463.851 865.899 494.549C865.899 555.948 916.847 593.833 999.148 593.833ZM1042.26 525.902C1004.37 525.902 981.512 510.88 981.512 486.712C981.512 461.892 1000.45 448.827 1048.14 442.949L1135.66 433.805V453.4C1135.66 497.163 1097.78 525.902 1042.26 525.902Z" fill="black"/>
|
||||
<path d="M1490.77 593.833C1604.43 593.833 1662.56 551.377 1662.56 482.793C1662.56 425.966 1629.9 394.613 1550.87 384.162L1452.23 373.059C1424.15 369.138 1412.39 361.953 1412.39 346.277C1412.39 327.336 1431.33 318.844 1474.44 318.844C1533.88 318.844 1575.03 332.561 1608.35 359.342L1661.25 306.434C1624.67 268.55 1561.32 247.648 1482.94 247.648C1372.55 247.648 1311.15 286.838 1311.15 352.809C1311.15 410.289 1349.03 442.295 1427.41 452.745L1516.25 463.196C1551.52 467.769 1561.97 474.302 1561.97 491.283C1561.97 510.88 1542.37 521.331 1496.65 521.331C1428.72 521.331 1383 503.041 1352.3 469.076L1292.21 518.717C1332.05 568.36 1399.98 593.833 1490.77 593.833Z" fill="black"/>
|
||||
<path d="M1754.78 331.255V469.076C1754.78 550.07 1800.5 591.221 1898.48 591.221C1928.53 591.221 1952.04 587.955 1974.25 581.423V496.508C1962.49 499.122 1948.12 501.734 1929.18 501.734C1888.03 501.734 1867.78 483.446 1867.78 444.908V331.255H1974.9V257.445H1867.78V137.914L1754.78 179.717V257.445H1681.62V331.255H1754.78Z" fill="black"/>
|
||||
<path d="M2137.13 257.445H2033.93V584.036H2146.93V461.892C2146.93 426.618 2154.77 394.613 2176.33 374.364C2193.31 358.687 2217.48 350.198 2251.44 350.198C2263.85 350.198 2273.65 351.502 2284.75 352.809V250.26C2277.57 248.954 2272.34 248.954 2263.2 248.954C2198.53 248.954 2154.77 286.185 2137.13 346.932V257.445Z" fill="black"/>
|
||||
<path d="M2508.05 593.833C2627.59 593.833 2711.85 530.475 2711.85 420.088C2711.85 310.353 2627.59 247.648 2508.05 247.648C2387.87 247.648 2303.61 310.353 2303.61 420.088C2303.61 530.475 2387.87 593.833 2508.05 593.833ZM2508.05 518.717C2453.19 518.717 2418.57 483.446 2418.57 420.088C2418.57 356.728 2453.19 322.763 2508.05 322.763C2562.27 322.763 2596.89 356.728 2596.89 420.088C2596.89 483.446 2562.27 518.717 2508.05 518.717Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
BIN
smoke/astro.build-main/public/assets/press/logomark-dark.png
Normal file
After Width: | Height: | Size: 53 KiB |
15
smoke/astro.build-main/public/assets/press/logomark-dark.svg
Normal file
|
@ -0,0 +1,15 @@
|
|||
<svg width="1281" height="1280" viewBox="0 0 1281 1280" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M815.931 94.6439C825.65 106.709 830.606 122.99 840.519 155.553L1057.06 866.901C976.999 825.368 889.964 795.413 798.174 779.252L657.182 302.798C654.875 295.002 647.715 289.654 639.585 289.654C631.434 289.654 624.26 295.03 621.972 302.853L482.688 779.011C390.471 795.1 303.038 825.109 222.634 866.793L440.24 155.388L440.24 155.388C450.183 122.882 455.154 106.629 464.874 94.5853C473.455 83.9531 484.616 75.6958 497.293 70.6002C511.652 64.8284 528.649 64.8284 562.642 64.8284H718.067C752.104 64.8284 769.123 64.8284 783.496 70.6123C796.184 75.7184 807.352 83.9923 815.931 94.6439Z" fill="url(#paint0_linear_709_106)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M841.843 900.754C806.146 931.279 734.895 952.097 652.822 952.097C552.089 952.097 467.659 920.737 445.256 878.561C437.247 902.732 435.45 930.396 435.45 948.068C435.45 948.068 430.173 1034.84 490.528 1095.2C490.528 1063.86 515.934 1038.46 547.273 1038.46C600.989 1038.46 600.929 1085.32 600.88 1123.34C600.878 1124.48 600.877 1125.61 600.877 1126.73C600.877 1184.44 636.147 1233.91 686.308 1254.77C678.816 1239.36 674.613 1222.05 674.613 1203.77C674.613 1148.73 706.926 1128.23 744.48 1104.41L744.481 1104.41C774.361 1085.46 807.56 1064.41 830.44 1022.17C842.379 1000.13 849.158 974.893 849.158 948.068C849.158 931.573 846.594 915.676 841.843 900.754Z" fill="#FF5D01"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M841.843 900.754C806.146 931.279 734.895 952.097 652.822 952.097C552.089 952.097 467.659 920.737 445.256 878.561C437.247 902.732 435.45 930.396 435.45 948.068C435.45 948.068 430.173 1034.84 490.528 1095.2C490.528 1063.86 515.934 1038.46 547.273 1038.46C600.989 1038.46 600.929 1085.32 600.88 1123.34C600.878 1124.48 600.877 1125.61 600.877 1126.73C600.877 1184.44 636.147 1233.91 686.308 1254.77C678.816 1239.36 674.613 1222.05 674.613 1203.77C674.613 1148.73 706.926 1128.23 744.48 1104.41L744.481 1104.41C774.361 1085.46 807.56 1064.41 830.44 1022.17C842.379 1000.13 849.158 974.893 849.158 948.068C849.158 931.573 846.594 915.676 841.843 900.754Z" fill="url(#paint1_linear_709_106)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_709_106" x1="883.889" y1="27.1132" x2="639.848" y2="866.902" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#F9FAFB"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_709_106" x1="1002.57" y1="652.45" x2="791.219" y2="1094.91" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF1639"/>
|
||||
<stop offset="1" stop-color="#FF1639" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
BIN
smoke/astro.build-main/public/assets/press/logomark-light.png
Normal file
After Width: | Height: | Size: 92 KiB |
|
@ -0,0 +1,15 @@
|
|||
<svg width="1280" height="1280" viewBox="0 0 1280 1280" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M815.039 94.6439C824.758 106.709 829.714 122.99 839.626 155.553L1056.17 866.901C976.107 825.368 889.072 795.413 797.281 779.252L656.29 302.798C653.983 295.002 646.822 289.654 638.693 289.654C630.542 289.654 623.368 295.03 621.08 302.853L481.795 779.011C389.579 795.1 302.146 825.109 221.741 866.793L439.347 155.388L439.348 155.388C449.291 122.882 454.262 106.629 463.982 94.5853C472.562 83.9531 483.723 75.6958 496.4 70.6002C510.76 64.8284 527.756 64.8284 561.749 64.8284H717.174C751.212 64.8284 768.23 64.8284 782.603 70.6123C795.292 75.7184 806.459 83.9923 815.039 94.6439Z" fill="url(#paint0_linear_709_110)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M840.951 900.754C805.253 931.279 734.002 952.097 651.929 952.097C551.197 952.097 466.767 920.737 444.363 878.561C436.354 902.732 434.558 930.396 434.558 948.068C434.558 948.068 429.281 1034.84 489.636 1095.2C489.636 1063.86 515.042 1038.46 546.381 1038.46C600.097 1038.46 600.036 1085.32 599.987 1123.34C599.986 1124.48 599.984 1125.61 599.984 1126.73C599.984 1184.44 635.255 1233.91 685.416 1254.77C677.924 1239.36 673.721 1222.05 673.721 1203.77C673.721 1148.73 706.034 1128.23 743.588 1104.41L743.588 1104.41C773.469 1085.46 806.668 1064.41 829.548 1022.17C841.486 1000.13 848.265 974.893 848.265 948.068C848.265 931.573 845.702 915.676 840.951 900.754Z" fill="#FF5D01"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M840.951 900.754C805.253 931.279 734.002 952.097 651.929 952.097C551.197 952.097 466.767 920.737 444.363 878.561C436.354 902.732 434.558 930.396 434.558 948.068C434.558 948.068 429.281 1034.84 489.636 1095.2C489.636 1063.86 515.042 1038.46 546.381 1038.46C600.097 1038.46 600.036 1085.32 599.987 1123.34C599.986 1124.48 599.984 1125.61 599.984 1126.73C599.984 1184.44 635.255 1233.91 685.416 1254.77C677.924 1239.36 673.721 1222.05 673.721 1203.77C673.721 1148.73 706.034 1128.23 743.588 1104.41L743.588 1104.41C773.469 1085.46 806.668 1064.41 829.548 1022.17C841.486 1000.13 848.265 974.893 848.265 948.068C848.265 931.573 845.702 915.676 840.951 900.754Z" fill="url(#paint1_linear_709_110)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_709_110" x1="882.997" y1="27.1132" x2="638.955" y2="866.902" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#000014"/>
|
||||
<stop offset="1" stop-color="#150426"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_709_110" x1="1001.68" y1="652.45" x2="790.326" y2="1094.91" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF1639"/>
|
||||
<stop offset="1" stop-color="#FF1639" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 22 KiB |
|
@ -0,0 +1,9 @@
|
|||
<svg width="2712" height="894" viewBox="0 0 2712 894" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M445.432 22.9832C452.722 32.0324 456.439 44.2432 463.873 68.6647L626.28 602.176C566.233 571.026 500.957 548.56 432.114 536.439L326.37 179.099C324.64 173.252 319.27 169.241 313.173 169.241C307.06 169.241 301.679 173.273 299.963 179.14L195.5 536.259C126.337 548.325 60.7627 570.832 0.458984 602.095L163.664 68.5412C171.121 44.1617 174.85 31.9718 182.139 22.9393C188.575 14.9651 196.946 8.77213 206.453 4.95048C217.223 0.621582 229.97 0.621582 255.465 0.621582H372.034C397.562 0.621582 410.326 0.621582 421.106 4.95951C430.622 8.78908 438.998 14.9946 445.432 22.9832Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M464.866 627.566C438.093 650.459 384.655 666.073 323.1 666.073C247.551 666.073 184.228 642.553 167.426 610.921C161.419 629.05 160.071 649.798 160.071 663.052C160.071 663.052 156.114 728.134 201.38 773.401C201.38 749.896 220.434 730.842 243.939 730.842C284.226 730.842 284.18 765.99 284.143 794.505C284.142 795.36 284.141 796.209 284.141 797.051C284.141 840.333 310.594 877.436 348.215 893.075C342.596 881.518 339.444 868.539 339.444 854.825C339.444 813.545 363.679 798.174 391.844 780.311C414.255 766.098 439.154 750.307 456.314 718.629C465.268 702.1 470.352 683.17 470.352 663.052C470.352 650.68 468.429 638.757 464.866 627.566Z" fill="white"/>
|
||||
<path d="M999.147 593.833C1067.08 593.833 1118.03 569.665 1138.93 528.516C1138.93 548.111 1140.23 568.36 1143.5 584.036H1255.19C1249.97 561.173 1247.35 529.82 1247.35 488.671V388.081C1247.35 292.717 1191.18 247.648 1066.42 247.648C957.344 247.648 884.188 292.717 875.696 366.527H991.962C995.881 334.521 1022.66 316.885 1066.42 316.885C1109.53 316.885 1133.7 334.521 1133.7 371.1V380.896L1015.48 391.347C957.997 397.227 925.338 407.023 902.476 422.7C878.309 439.028 865.898 463.851 865.898 494.549C865.898 555.948 916.847 593.833 999.147 593.833ZM1042.26 525.902C1004.37 525.902 981.511 510.88 981.511 486.712C981.511 461.892 1000.45 448.827 1048.14 442.949L1135.66 433.805V453.4C1135.66 497.163 1097.78 525.902 1042.26 525.902Z" fill="white"/>
|
||||
<path d="M1490.77 593.833C1604.42 593.833 1662.56 551.377 1662.56 482.793C1662.56 425.966 1629.9 394.613 1550.87 384.162L1452.23 373.059C1424.15 369.138 1412.39 361.953 1412.39 346.277C1412.39 327.336 1431.33 318.844 1474.44 318.844C1533.88 318.844 1575.03 332.561 1608.35 359.342L1661.25 306.434C1624.67 268.55 1561.32 247.648 1482.93 247.648C1372.55 247.648 1311.15 286.838 1311.15 352.809C1311.15 410.289 1349.03 442.295 1427.41 452.745L1516.25 463.196C1551.52 467.769 1561.97 474.302 1561.97 491.283C1561.97 510.88 1542.37 521.331 1496.65 521.331C1428.72 521.331 1383 503.041 1352.3 469.076L1292.2 518.717C1332.05 568.36 1399.98 593.833 1490.77 593.833Z" fill="white"/>
|
||||
<path d="M1754.78 331.255V469.076C1754.78 550.07 1800.5 591.221 1898.48 591.221C1928.53 591.221 1952.04 587.955 1974.25 581.423V496.508C1962.49 499.122 1948.12 501.734 1929.18 501.734C1888.03 501.734 1867.78 483.446 1867.78 444.908V331.255H1974.9V257.445H1867.78V137.914L1754.78 179.717V257.445H1681.62V331.255H1754.78Z" fill="white"/>
|
||||
<path d="M2137.13 257.445H2033.93V584.036H2146.93V461.892C2146.93 426.618 2154.77 394.613 2176.33 374.364C2193.31 358.687 2217.48 350.198 2251.44 350.198C2263.85 350.198 2273.65 351.502 2284.75 352.809V250.26C2277.57 248.954 2272.34 248.954 2263.2 248.954C2198.53 248.954 2154.77 286.185 2137.13 346.932V257.445Z" fill="white"/>
|
||||
<path d="M2508.05 593.833C2627.59 593.833 2711.85 530.475 2711.85 420.088C2711.85 310.353 2627.59 247.648 2508.05 247.648C2387.87 247.648 2303.61 310.353 2303.61 420.088C2303.61 530.475 2387.87 593.833 2508.05 593.833ZM2508.05 518.717C2453.19 518.717 2418.57 483.446 2418.57 420.088C2418.57 356.728 2453.19 322.763 2508.05 322.763C2562.27 322.763 2596.89 356.728 2596.89 420.088C2596.89 483.446 2562.27 518.717 2508.05 518.717Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 21 KiB |
|
@ -0,0 +1,9 @@
|
|||
<svg width="2712" height="894" viewBox="0 0 2712 894" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M445.433 22.9832C452.722 32.0324 456.439 44.2432 463.873 68.6647L626.281 602.176C566.234 571.026 500.957 548.56 432.115 536.439L326.371 179.099C324.641 173.252 319.27 169.241 313.173 169.241C307.06 169.241 301.68 173.273 299.963 179.14L195.5 536.259C126.338 548.325 60.7632 570.832 0.459473 602.095L163.664 68.5412C171.121 44.1617 174.85 31.9718 182.14 22.9393C188.575 14.9651 196.946 8.77213 206.454 4.95048C217.224 0.621582 229.971 0.621582 255.466 0.621582H372.034C397.562 0.621582 410.326 0.621582 421.106 4.95951C430.622 8.78908 438.998 14.9946 445.433 22.9832Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M464.867 627.566C438.094 650.459 384.655 666.073 323.101 666.073C247.551 666.073 184.229 642.553 167.426 610.921C161.419 629.05 160.072 649.798 160.072 663.052C160.072 663.052 156.114 728.134 201.381 773.401C201.381 749.896 220.435 730.842 243.939 730.842C284.226 730.842 284.181 765.99 284.144 794.505C284.143 795.36 284.142 796.209 284.142 797.051C284.142 840.333 310.595 877.436 348.215 893.075C342.596 881.518 339.444 868.539 339.444 854.825C339.444 813.544 363.679 798.174 391.845 780.311C414.255 766.098 439.155 750.307 456.315 718.629C465.268 702.1 470.353 683.17 470.353 663.052C470.353 650.68 468.43 638.757 464.867 627.566Z" fill="black"/>
|
||||
<path d="M999.148 593.833C1067.08 593.833 1118.03 569.665 1138.93 528.516C1138.93 548.111 1140.24 568.36 1143.5 584.036H1255.2C1249.97 561.173 1247.36 529.82 1247.36 488.671V388.081C1247.36 292.717 1191.18 247.648 1066.43 247.648C957.345 247.648 884.189 292.717 875.697 366.527H991.963C995.882 334.521 1022.66 316.885 1066.43 316.885C1109.53 316.885 1133.7 334.521 1133.7 371.1V380.896L1015.48 391.347C957.998 397.227 925.339 407.023 902.477 422.7C878.31 439.028 865.899 463.851 865.899 494.549C865.899 555.948 916.847 593.833 999.148 593.833ZM1042.26 525.902C1004.37 525.902 981.512 510.88 981.512 486.712C981.512 461.892 1000.45 448.827 1048.14 442.949L1135.66 433.805V453.4C1135.66 497.163 1097.78 525.902 1042.26 525.902Z" fill="black"/>
|
||||
<path d="M1490.77 593.833C1604.43 593.833 1662.56 551.377 1662.56 482.793C1662.56 425.966 1629.9 394.613 1550.87 384.162L1452.24 373.059C1424.15 369.138 1412.39 361.953 1412.39 346.277C1412.39 327.336 1431.33 318.844 1474.44 318.844C1533.88 318.844 1575.03 332.561 1608.35 359.342L1661.25 306.434C1624.68 268.55 1561.32 247.648 1482.94 247.648C1372.55 247.648 1311.15 286.838 1311.15 352.809C1311.15 410.289 1349.03 442.295 1427.41 452.745L1516.25 463.196C1551.52 467.769 1561.97 474.302 1561.97 491.283C1561.97 510.88 1542.37 521.331 1496.65 521.331C1428.72 521.331 1383 503.041 1352.3 469.076L1292.21 518.717C1332.05 568.36 1399.98 593.833 1490.77 593.833Z" fill="black"/>
|
||||
<path d="M1754.78 331.255V469.076C1754.78 550.07 1800.5 591.221 1898.48 591.221C1928.53 591.221 1952.04 587.955 1974.25 581.423V496.508C1962.49 499.122 1948.12 501.734 1929.18 501.734C1888.03 501.734 1867.78 483.446 1867.78 444.908V331.255H1974.9V257.445H1867.78V137.914L1754.78 179.717V257.445H1681.62V331.255H1754.78Z" fill="black"/>
|
||||
<path d="M2137.13 257.445H2033.93V584.036H2146.93V461.892C2146.93 426.618 2154.77 394.613 2176.33 374.364C2193.31 358.687 2217.48 350.198 2251.44 350.198C2263.85 350.198 2273.65 351.502 2284.75 352.809V250.26C2277.57 248.954 2272.34 248.954 2263.2 248.954C2198.53 248.954 2154.77 286.185 2137.13 346.932V257.445Z" fill="black"/>
|
||||
<path d="M2508.05 593.833C2627.59 593.833 2711.85 530.475 2711.85 420.088C2711.85 310.353 2627.59 247.648 2508.05 247.648C2387.87 247.648 2303.61 310.353 2303.61 420.088C2303.61 530.475 2387.87 593.833 2508.05 593.833ZM2508.05 518.717C2453.19 518.717 2418.57 483.446 2418.57 420.088C2418.57 356.728 2453.19 322.763 2508.05 322.763C2562.27 322.763 2596.89 356.728 2596.89 420.088C2596.89 483.446 2562.27 518.717 2508.05 518.717Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 8.1 KiB |
|
@ -0,0 +1,4 @@
|
|||
<svg width="1280" height="1280" viewBox="0 0 1280 1280" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M815.039 94.6439C824.758 106.709 829.714 122.99 839.626 155.553L1056.17 866.902C976.107 825.368 889.072 795.413 797.281 779.252L656.29 302.798C653.983 295.002 646.822 289.654 638.693 289.654C630.542 289.654 623.368 295.03 621.08 302.853L481.795 779.011C389.579 795.1 302.146 825.109 221.741 866.793L439.347 155.388L439.348 155.388C449.291 122.882 454.262 106.629 463.982 94.5853C472.562 83.9531 483.723 75.6958 496.4 70.6002C510.76 64.8284 527.756 64.8284 561.749 64.8284H717.174C751.212 64.8284 768.23 64.8284 782.603 70.6123C795.292 75.7184 806.459 83.9923 815.039 94.6439Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M840.951 900.754C805.253 931.279 734.002 952.097 651.929 952.097C551.197 952.097 466.767 920.737 444.363 878.561C436.354 902.732 434.558 930.396 434.558 948.068C434.558 948.068 429.281 1034.84 489.636 1095.2C489.636 1063.86 515.042 1038.46 546.381 1038.46C600.097 1038.46 600.036 1085.32 599.987 1123.34C599.986 1124.48 599.984 1125.61 599.984 1126.73C599.984 1184.44 635.255 1233.91 685.416 1254.77C677.924 1239.36 673.721 1222.05 673.721 1203.77C673.721 1148.73 706.034 1128.23 743.588 1104.41L743.588 1104.41C773.469 1085.46 806.668 1064.41 829.548 1022.17C841.486 1000.13 848.265 974.893 848.265 948.068C848.265 931.573 845.702 915.676 840.951 900.754Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 7.4 KiB |
|
@ -0,0 +1,4 @@
|
|||
<svg width="1280" height="1280" viewBox="0 0 1280 1280" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M815.039 94.6439C824.758 106.709 829.714 122.99 839.626 155.553L1056.17 866.902C976.107 825.368 889.072 795.413 797.281 779.252L656.29 302.798C653.983 295.002 646.822 289.654 638.693 289.654C630.542 289.654 623.368 295.03 621.08 302.853L481.795 779.011C389.579 795.1 302.146 825.109 221.741 866.793L439.347 155.388L439.348 155.388C449.291 122.882 454.262 106.629 463.982 94.5853C472.562 83.9531 483.723 75.6958 496.4 70.6002C510.76 64.8284 527.756 64.8284 561.749 64.8284H717.174C751.212 64.8284 768.23 64.8284 782.603 70.6123C795.292 75.7184 806.459 83.9923 815.039 94.6439Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M840.951 900.754C805.253 931.279 734.002 952.097 651.929 952.097C551.197 952.097 466.767 920.737 444.363 878.561C436.354 902.732 434.558 930.396 434.558 948.068C434.558 948.068 429.281 1034.84 489.636 1095.2C489.636 1063.86 515.042 1038.46 546.381 1038.46C600.097 1038.46 600.036 1085.32 599.987 1123.34C599.986 1124.48 599.984 1125.61 599.984 1126.73C599.984 1184.44 635.255 1233.91 685.416 1254.77C677.924 1239.36 673.721 1222.05 673.721 1203.77C673.721 1148.73 706.034 1128.23 743.588 1104.41L743.588 1104.41C773.469 1085.46 806.668 1064.41 829.548 1022.17C841.486 1000.13 848.265 974.893 848.265 948.068C848.265 931.573 845.702 915.676 840.951 900.754Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -1,3 +0,0 @@
|
|||
if (window.matchMedia('(hover: hover)').matches) {
|
||||
import('/scripts/konami.js').then(mod => mod.init());
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
// Aha! These are not analytics at all!
|
||||
class KonamiCode {
|
||||
enabled = false;
|
||||
keys = ["ArrowUp", "ArrowUp", "ArrowDown", "ArrowDown", "ArrowLeft", "ArrowRight", "ArrowLeft", "ArrowRight", "b", "a"];
|
||||
accepted = [...new Set(this.keys)];
|
||||
inputs = [];
|
||||
|
||||
constructor({ enable, disable }) {
|
||||
this.enable = enable;
|
||||
this.disable = disable;
|
||||
this.handleKey = this.handleKey.bind(this);
|
||||
document.addEventListener('keydown', this.handleKey);
|
||||
}
|
||||
|
||||
handleKey({ key }) {
|
||||
if (this.enabled) {
|
||||
this.reset();
|
||||
return;
|
||||
}
|
||||
if (!this.accepted.includes(key)) return;
|
||||
|
||||
if (this.keys[this.inputs.length] === key) {
|
||||
this.handleInput(key)
|
||||
} else {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
handleInput(key) {
|
||||
this.inputs.push(key);
|
||||
|
||||
if (this.inputs.length === 10) {
|
||||
this.handleMatch();
|
||||
}
|
||||
}
|
||||
|
||||
handleMatch() {
|
||||
this.enabled = true;
|
||||
this.enable();
|
||||
this.inputs = [];
|
||||
}
|
||||
|
||||
reset() {
|
||||
if (this.enabled) {
|
||||
this.enabled = false;
|
||||
this.disable();
|
||||
}
|
||||
if (this.inputs.length) {
|
||||
this.inputs = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function init() {
|
||||
new KonamiCode({
|
||||
enable: () => document.body.classList.add('🥚'),
|
||||
disable: () => document.body.classList.remove('🥚'),
|
||||
});
|
||||
}
|
|
@ -137,10 +137,6 @@ body {
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
.transition #root {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@property --border-radius {
|
||||
syntax: '<integer>';
|
||||
inherits: true;
|
||||
|
@ -184,74 +180,6 @@ small {
|
|||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
.pixel {
|
||||
--border-radius: 8;
|
||||
--pixel-size: 4;
|
||||
--background: var(--gradient-pop-1);
|
||||
position: relative;
|
||||
border-radius: calc(var(--border-radius) * 1px);
|
||||
}
|
||||
.pixel::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: calc(var(--pixel-size) * 1px);
|
||||
right: 0;
|
||||
bottom: calc(var(--pixel-size) * 1px);
|
||||
left: 0;
|
||||
background: var(--background);
|
||||
z-index: -1;
|
||||
}
|
||||
.pixel::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: calc(var(--pixel-size) * 1px);
|
||||
bottom: 0;
|
||||
left: calc(var(--pixel-size) * 1px);
|
||||
background: var(--background);
|
||||
z-index: -1;
|
||||
}
|
||||
.pixel.variant-outline {
|
||||
background: rgba(255, 255, 255, 0);
|
||||
border-radius: 0;
|
||||
}
|
||||
.pixel.variant-outline::before {
|
||||
background: rgba(255, 255, 255, 0);
|
||||
border: calc(var(--pixel-size) * 1px) solid var(--background);
|
||||
border-top: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.pixel.variant-outline::after {
|
||||
background: rgba(255, 255, 255, 0);
|
||||
border: calc(var(--pixel-size) * 1px) solid var(--background);
|
||||
border-right: 0;
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
@supports (background: paint(pixel)) {
|
||||
.js .pixel {
|
||||
background: none !important;
|
||||
}
|
||||
.js .pixel::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
z-index: -1;
|
||||
overflow: hidden;
|
||||
border-radius: 0;
|
||||
background: var(--background);
|
||||
-webkit-mask-image: paint(pixel);
|
||||
mask-image: paint(pixel);
|
||||
}
|
||||
.js .pixel::after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: var(--font-body);
|
||||
color: var(--color-midnight);
|
||||
|
@ -288,7 +216,7 @@ html {
|
|||
width: 1px;
|
||||
}
|
||||
|
||||
.container {
|
||||
.astro-container {
|
||||
max-width: 40rem;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 0.5em;
|
||||
|
@ -297,32 +225,32 @@ html {
|
|||
}
|
||||
|
||||
@media (min-width: 40rem) {
|
||||
.container {
|
||||
.astro-container {
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 52rem) {
|
||||
.container {
|
||||
.astro-container {
|
||||
max-width: 50rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 64rem) {
|
||||
.container {
|
||||
.astro-container {
|
||||
max-width: 62rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 82rem) {
|
||||
.container {
|
||||
.astro-container {
|
||||
max-width: 80rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 92rem) {
|
||||
.container {
|
||||
.astro-container {
|
||||
max-width: 90rem;
|
||||
}
|
||||
}
|
||||
|
@ -355,82 +283,19 @@ p, .body-md {
|
|||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.container {
|
||||
.elevation-sm {
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.astro-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#article :is(h1, h2, h3, h4, h5, h6) {
|
||||
font-family: var(--font-display);
|
||||
line-height: 1.1;
|
||||
margin-bottom: 1.25rem;
|
||||
color: var(--color-dusk);
|
||||
}
|
||||
#article hr {
|
||||
border: 0;
|
||||
border-top: 1px solid var(--color-dawn);
|
||||
margin-left: -2rem;
|
||||
margin-right: -2rem;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
#article h1 {
|
||||
--fill: var(--gradient-pop-1);
|
||||
font-size: 3rem;
|
||||
font-size: var(--size-800);
|
||||
|
||||
}
|
||||
#article h2 {
|
||||
font-size: 2rem;
|
||||
font-size: var(--size-600);
|
||||
margin-top: 2em;
|
||||
margin-bottom: -0.25em;
|
||||
}
|
||||
|
||||
#article code {
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 400;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
#article code:not([class]) {
|
||||
font-size: 0.85em;
|
||||
color: var(--color-purple);
|
||||
}
|
||||
|
||||
#article code:not([class])::before {
|
||||
content: '\`';
|
||||
}
|
||||
#article code:not([class])::after {
|
||||
content: '\`';
|
||||
}
|
||||
|
||||
.astro-code > code::before,
|
||||
.astro-code > code::after {
|
||||
content: none !important;
|
||||
}
|
||||
|
||||
#article img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#article :is(h2, h3, h4, h5, h6) a {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
text-decoration: none !important;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#article :is(h2, h3, h4, h5, h6) a::before {
|
||||
content: "#";
|
||||
width: 1em;
|
||||
margin-left: 0.25em;
|
||||
color: inherit;
|
||||
opacity: 0;
|
||||
transition: opacity 200ms cubic-bezier(0.23, 1, 0.320, 1);
|
||||
order: 999;
|
||||
}
|
||||
|
||||
@media (min-width: 50rem) {
|
||||
#content :is(h2, h3, h4, h5, h6) a::before {
|
||||
order: initial;
|
||||
|
@ -438,430 +303,6 @@ p, .body-md {
|
|||
}
|
||||
}
|
||||
|
||||
#article :is(h2, h3, h4, h5, h6) a:is(:active, :visited, :hover, :focus) {
|
||||
color: var(--color-dusk);
|
||||
}
|
||||
|
||||
#article :is(h2, h3, h4, h5, h6) a:active::before,
|
||||
#article :is(h2, h3, h4, h5, h6) a:hover::before,
|
||||
#article :is(h2, h3, h4, h5, h6) a:focus::before {
|
||||
opacity: 0.6 !important;
|
||||
}
|
||||
|
||||
#article :is(strong, b) {
|
||||
font-family: inherit;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#article :is(em, i) {
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
#article :is(ul:not([role="list"]), ol:not([role="list"])) {
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
|
||||
#article :where(ul:not([role="list"])) {
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
#article :where(ul:not([role="list"]) > li + li) {
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
|
||||
#article ::marker {
|
||||
color: rgba(var(--color-midnight-rgb), 0.5);
|
||||
}
|
||||
|
||||
#article pre > code:not([class*='language']) {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#article pre > code {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
#article pre {
|
||||
position: relative;
|
||||
--padding-block: 1rem;
|
||||
--padding-inline: 2rem;
|
||||
padding: var(--padding-block) var(--padding-inline);
|
||||
padding-right: calc(var(--padding-inline) * 2);
|
||||
margin-left: calc(var(--padding-inline) * -1);
|
||||
margin-right: calc(var(--padding-inline) * -1);
|
||||
font-family: var(--font-mono);
|
||||
|
||||
line-height: 1.5;
|
||||
font-size: 0.85em;
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
#article pre {
|
||||
background: linear-gradient(to bottom, var(--color-midnight), #1F1638);
|
||||
color: white;
|
||||
}
|
||||
|
||||
#article table {
|
||||
width: 100%;
|
||||
padding: var(--padding-block) 0;
|
||||
margin: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
/* Zebra striping */
|
||||
#article tr:nth-of-type(odd) {
|
||||
background: var(--theme-bg-hover);
|
||||
}
|
||||
#article th {
|
||||
background: var(--color-black);
|
||||
color: var(--theme-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
#article td,
|
||||
#article th {
|
||||
padding: 6px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Code */
|
||||
|
||||
.language-css > code,
|
||||
.language-sass > code,
|
||||
.language-scss > code {
|
||||
color: #fd9170;
|
||||
}
|
||||
|
||||
.language-diff .token.prefix.deleted,
|
||||
.language-diff .token.prefix.inserted {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
[class*='language-'] .namespace {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.token.plain-text,
|
||||
[class*='language-bash'] span.token,
|
||||
[class*='language-shell'] span.token {
|
||||
color: hsla(var(--color-gray-90), 1);
|
||||
}
|
||||
|
||||
[class*='language-bash'] span.token,
|
||||
[class*='language-shell'] span.token {
|
||||
font-style: bold;
|
||||
}
|
||||
|
||||
.token.prolog,
|
||||
.token.comment,
|
||||
[class*='language-bash'] span.token.comment,
|
||||
[class*='language-shell'] span.token.comment {
|
||||
color: rgba(255, 255, 255, 0.67);
|
||||
}
|
||||
|
||||
.token.front-matter-block {
|
||||
color: white;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.tag,
|
||||
.token.unit,
|
||||
.token.url,
|
||||
.token.variable,
|
||||
.token.entity,
|
||||
.token.deleted {
|
||||
color: #fa5e5b;
|
||||
}
|
||||
|
||||
.token.boolean,
|
||||
.token.constant,
|
||||
.token.doctype,
|
||||
.token.number,
|
||||
.token.regex,
|
||||
.token.builtin,
|
||||
.token.class,
|
||||
.token.hexcode,
|
||||
.token.class-name,
|
||||
.token.attr-name {
|
||||
color: hsla(var(--color-yellow), 1);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attribute,
|
||||
.token.attr-value .token.punctuation,
|
||||
.token.attr-value,
|
||||
.token.pseudo-class,
|
||||
.token.pseudo-element,
|
||||
.token.string {
|
||||
color: hsla(var(--color-green), 1);
|
||||
}
|
||||
|
||||
.token.symbol,
|
||||
.token.function,
|
||||
.token.id,
|
||||
.token.important {
|
||||
color: hsla(var(--color-blue), 1);
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.id {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.cdata,
|
||||
.token.char,
|
||||
.token.property {
|
||||
color: #23b1af;
|
||||
}
|
||||
|
||||
.token.inserted {
|
||||
color: hsla(var(--color-green), 1);
|
||||
}
|
||||
|
||||
.token.keyword {
|
||||
color: #ff657c;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.operator {
|
||||
color: hsla(var(--color-gray-70), 1);
|
||||
}
|
||||
|
||||
.token.attr-value .token.attr-equals,
|
||||
.token.punctuation {
|
||||
color: hsla(var(--color-gray-80), 1);
|
||||
}
|
||||
|
||||
#nav {
|
||||
--offset-height: calc(var(--offset) * 1rem);
|
||||
width: 100%;
|
||||
position: sticky;
|
||||
top: calc((var(--offset-height) * -1) - 1px);
|
||||
margin-top: -2rem;
|
||||
padding: 0.5rem 0;
|
||||
background: linear-gradient(0deg, rgba(var(--color-tan-rgb), 0.7), rgba(var(--color-tan-rgb), 1));
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
backdrop-filter: blur(10px);
|
||||
z-index: 2;
|
||||
}
|
||||
#nav.margin-bottom {
|
||||
margin-bottom: -4.5rem;
|
||||
}
|
||||
#nav.invert {
|
||||
background: transparent;
|
||||
color: white;
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
#nav.invert a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
#nav::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: var(--offset-height);
|
||||
z-index: -2;
|
||||
}
|
||||
#nav.invert::before {
|
||||
background: #1f1638;
|
||||
margin-top: -0.5rem;
|
||||
}
|
||||
|
||||
#nav::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: var(--offset-height);
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
box-shadow: var(--shadow-md);
|
||||
opacity: 0;
|
||||
transition-property: opacity;
|
||||
transition-duration: 200ms;
|
||||
transition-timing-function: cubic-bezier(0.23, 1, 0.320, 1);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
#nav[stuck]::after {
|
||||
opacity: 0.5;
|
||||
transition-duration: 600ms;
|
||||
}
|
||||
|
||||
#nav ul {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.33rem;
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
#nav li {
|
||||
color: var(--color-dusk);
|
||||
font-family: var(--font-display);
|
||||
font-weight: 400;
|
||||
font-size: var(--size-500);
|
||||
}
|
||||
#nav.invert li {
|
||||
color: white;
|
||||
}
|
||||
#nav li + li {
|
||||
margin-left: 0;
|
||||
}
|
||||
#nav [aria-current="page"] {
|
||||
font-weight: 700;
|
||||
}
|
||||
#nav .logo {
|
||||
font-size: 1rem;
|
||||
margin-right: auto;
|
||||
}
|
||||
#nav .logo a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--color-midnight);
|
||||
}
|
||||
#nav .logo a:hover,
|
||||
#nav .logo a:focus {
|
||||
color: var(--color-midnight);
|
||||
}
|
||||
#nav .logo a:active {
|
||||
color: var(--color-midnight);
|
||||
}
|
||||
#nav .logo svg {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
#nav .logomark {
|
||||
color: inherit;
|
||||
}
|
||||
#nav.invert .logo svg {
|
||||
color: white;
|
||||
fill: white;
|
||||
}
|
||||
#nav .wordmark {
|
||||
display: none;
|
||||
color: inherit;
|
||||
margin-top: -0.5rem;
|
||||
}
|
||||
#nav .hidden-mobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 52rem) {
|
||||
#nav {
|
||||
/* height: calc(2px + 4.5rem); */
|
||||
}
|
||||
#nav .logo svg {
|
||||
transform: scale(1);
|
||||
}
|
||||
#nav .wordmark {
|
||||
display: block;
|
||||
}
|
||||
#nav .hidden-mobile {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
#nav a {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
color: var(--color-midnight);
|
||||
text-decoration: none;
|
||||
transition: all 200ms cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||
transition-property: transform, color;
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
#nav a:focus,
|
||||
#nav a:hover {
|
||||
color: var(--color-purple);
|
||||
}
|
||||
#nav a:active {
|
||||
color: var(--color-blue);
|
||||
}
|
||||
|
||||
#nav .icon a svg {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
#nav .icon a:focus svg,
|
||||
#nav .icon a:hover svg {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
#nav [astro-icon="logo"] {
|
||||
margin-right: 0.25em;
|
||||
transform: translateY(0.5em);
|
||||
}
|
||||
|
||||
.checklist {
|
||||
font-size: var(--size-500);
|
||||
--marker-size: 3rem;
|
||||
display: grid;
|
||||
gap: 0.75rem;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
max-width: 72rem;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
@media (min-width: 24rem) {
|
||||
.checklist {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.checklist-item {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 40rem) {
|
||||
.checklist {
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 52rem) {
|
||||
.checklist {
|
||||
grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
.checklist > li {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.checklist-marker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: var(--marker-size);
|
||||
height: var(--marker-size);
|
||||
background: var(--color-dawn);
|
||||
color: var(--color-midnight);
|
||||
border-radius: 50%;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.checklist-text {
|
||||
font-size: var(--size-600);
|
||||
}
|
||||
|
||||
.checklist > li > svg {
|
||||
width: var(--marker-size);
|
||||
height: var(--marker-size);
|
||||
}
|
||||
|
||||
.egg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
@ -872,41 +313,6 @@ p, .body-md {
|
|||
pointer-events: none;
|
||||
}
|
||||
|
||||
noscript {
|
||||
order: -1;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--size-600);
|
||||
text-align: center;
|
||||
color: var(--color-midnight);
|
||||
background: linear-gradient(to bottom, var(--color-tan), white);
|
||||
}
|
||||
noscript::before {
|
||||
--size: var(--size-1000);
|
||||
padding-top: var(--size);
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
content: 'You need to enable JavaScript to view this site.';
|
||||
background-size: var(--size);
|
||||
background-position: center top;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 140 140'%3E%3Cg fill='%23514375'%3E%3Cpath d='M129.7 100v20h-10v-20z'/%3E%3Cpath d='M119.69 100h20v10h-20zM10 100v20h10v-20z'/%3E%3Cpath d='M20 100H0v10h20zm0-90H0v10h20z'/%3E%3Cpath d='M20 20V0H10v20zm79.69 30h20v10h-20zm-39.21 0h20v10h-20zM29.73 20h80v10h-80zm-9.97 50h99.93v10H19.76zm10 10h79.93v10H29.76zm-.03 10h20v10h-20zm30.75 0h20v10h-20zm29.21 0h20v10h-20zM19.73 30h100v10h-100zm0 10h100v10h-100zm0 20h100v10h-100zm0-10h20v10h-20zM120 10h20v10h-20z'/%3E%3Cpath d='M120 20V0h10v20z'/%3E%3C/g%3E%3C/svg%3E%0A");
|
||||
}
|
||||
noscript::after {
|
||||
--size: var(--size-1000);
|
||||
content: 'Just kidding—you\'re going to love Astro!';
|
||||
font-size: 0.75em;
|
||||
padding-bottom: var(--size);
|
||||
background-size: var(--size);
|
||||
background-position: 50% 100%;
|
||||
background-image: url("data:image/svg+xml,%3Csvg width='140' height='141' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23af43ff' d='M85 80.325v-20h10v20zM45 80.325v-20h10v20zM65 40.325h10v60H65z'/%3E%3Cpath fill='%23af43ff' d='M55 80.325h30v10H55z'/%3E%3C/svg%3E");
|
||||
animation: bounce 1s steps(4) alternate-reverse infinite;
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
from {
|
||||
background-position: 50% 100%;
|
||||
|
@ -916,195 +322,6 @@ noscript::after {
|
|||
}
|
||||
}
|
||||
|
||||
not-marquee {
|
||||
--color: var(--color-midnight);
|
||||
--height: 2rem;
|
||||
--speed: 25;
|
||||
--gap: var(--size-1000);
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
height: var(--height);
|
||||
overflow: hidden;
|
||||
|
||||
border-top: 1px solid var(--color);
|
||||
margin-top: -1px;
|
||||
border-bottom: 1px solid var(--color);
|
||||
font-family: var(--font-display);
|
||||
text-transform: uppercase;
|
||||
font-size: 0.75em;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
background: white;
|
||||
z-index: 3;
|
||||
|
||||
}
|
||||
|
||||
not-marquee::before,
|
||||
not-marquee::after {
|
||||
content: "";
|
||||
width: var(--gap);
|
||||
height: var(--height);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: var(--right, auto);
|
||||
bottom: 0;
|
||||
left: var(--left, auto);
|
||||
background: linear-gradient(var(--dir, to right), white, white 5%, rgba(255, 255, 255, 0));
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
not-marquee::before {
|
||||
--left: calc(var(--height) - 4px);
|
||||
--dir: to right;
|
||||
}
|
||||
not-marquee::after {
|
||||
--right: 0;
|
||||
--dir: to left;
|
||||
}
|
||||
|
||||
not-marquee input[type="checkbox"] {
|
||||
--size: var(--height);
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
border-radius: 0;
|
||||
z-index: 2;
|
||||
background: white;
|
||||
margin-top: -1px;
|
||||
margin-left: -1px;
|
||||
border: 1px solid var(--color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
not-marquee input[type="checkbox"]:hover,
|
||||
not-marquee input[type="checkbox"]:focus {
|
||||
background: var(--color-dusk);
|
||||
}
|
||||
|
||||
not-marquee input[type="checkbox"]:active {
|
||||
background: var(--color-purple);
|
||||
}
|
||||
|
||||
not-marquee input[type="checkbox"]:hover::before,
|
||||
not-marquee input[type="checkbox"]:focus::before,
|
||||
not-marquee input[type="checkbox"]:active::before {
|
||||
filter: saturate(0) brightness(0) invert(1);
|
||||
}
|
||||
|
||||
not-marquee input[type="checkbox"]::before {
|
||||
content: "";
|
||||
width: calc(var(--size) * 0.75);
|
||||
height: calc(var(--size) * 0.75);
|
||||
}
|
||||
|
||||
not-marquee input[type="checkbox"]::before {
|
||||
/* Pause */
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M14 19h4V5h-4M6 19h4V5H6v14z' fill='%2331274a'%3E%3C/path%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
not-marquee input[type="checkbox"]:checked::before {
|
||||
/* Play */
|
||||
background-position: -1px center;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M8 5.14v14l11-7l-11-7z' fill='%2331274a'%3E%3C/path%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
not-marquee input[type="checkbox"]:checked ~ .track,
|
||||
not-marquee .track:hover {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
|
||||
not-marquee .track {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
color: var(--color);
|
||||
transition: color 300ms cubic-bezier(0.23, 1, 0.320, 1);
|
||||
}
|
||||
|
||||
not-marquee a.track:hover,
|
||||
not-marquee a.track:focus {
|
||||
color: var(--color-purple);
|
||||
}
|
||||
|
||||
not-marquee a.track:active {
|
||||
color: var(--color-blue);
|
||||
}
|
||||
|
||||
not-marquee .group {
|
||||
position: absolute;
|
||||
display: block;
|
||||
animation: marquee calc(var(--speed) * 1s) linear infinite;
|
||||
animation-play-state: inherit;
|
||||
user-select: none;
|
||||
padding-left: var(--gap);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
not-marquee .track {
|
||||
animation-play-state: paused;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
not-marquee .group > span + span {
|
||||
padding-left: var(--gap);
|
||||
}
|
||||
|
||||
@keyframes marquee {
|
||||
from { transform: translateX(calc(100% * var(--i, 0))) }
|
||||
to { transform: translateX(calc(100% * calc(var(--i, 0) - 1))) }
|
||||
}
|
||||
|
||||
.skip-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
overflow-x: hidden;
|
||||
text-align: center;
|
||||
|
||||
background-color: white;
|
||||
border-bottom: 1px solid transparent;
|
||||
font-family: var(--font-display);
|
||||
text-transform: uppercase;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
background: white;
|
||||
z-index: 5;
|
||||
|
||||
/* Visually hidden */
|
||||
clip: rect(0 0 0 0);
|
||||
clip-path: inset(50%);
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
width: 1px;
|
||||
}
|
||||
.skip-link:focus {
|
||||
width: 100vw;
|
||||
height: 48px;
|
||||
position: fixed;
|
||||
clip: initial;
|
||||
clip-path: initial;
|
||||
|
||||
background: var(--color-purple);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.🥚 {
|
||||
--cursor-default: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' fill='%2331274a' viewBox='0 0 128 128'%3E%3Cpath fill='%23fff' d='M3.37 0 .11.01C-.05 24.95.04 49.9 0 74.82c.05 13.23-.1 26.46.09 39.68 4.48 0 8.97.04 13.46 0 .12-1.92.15-3.86.15-5.8v-.88h.87c1.91.02 3.82 0 5.72-.01.04-1.96.18-3.92-.03-5.88l-.12-1.1 1.09.15c1.97.25 3.95.08 5.92.04.04-1.88.08-3.77.1-5.65v-.86h.87c1.49.02 2.98 0 4.47-.08l.99-.05-.08.98c-.3 4.12.39 8.24.16 12.36 1.95.06 3.89.09 5.83.1l.85.02.01.84c.04 4.18.03 8.35.1 12.52 1.92.04 3.84.06 5.76.07h.86l.01.85c.03 1.95.05 3.88.04 5.83 4.52.06 9.04.05 13.56.03.16-1.92.24-3.86.1-5.81l-.07-.96.96.03c1.91.05 3.84.03 5.73-.02.07-4.5.04-9 0-13.49-1.94-.05-3.87-.08-5.8-.1h-.84l-.01-.85c-.07-4.18-.04-8.35-.06-12.53-1.93-.07-3.88-.1-5.83-.06l-.92.03.03-.92c.07-1.62.1-3.22.09-4.82v-.87h.87c8.63-.01 17.27 0 25.91-.1.06-4.48.07-8.96-.01-13.44-1.94 0-3.88-.02-5.82-.05h-.85v-.85c-.03-1.94-.05-3.89-.04-5.83a252.3 252.3 0 0 0-5.8-.07h-.85l-.01-.85c-.03-1.93-.04-3.85-.08-5.78-1.93-.09-3.87-.14-5.82-.12l-.88.01v-.88a567 567 0 0 0-.03-5.84 226 226 0 0 1-5.83-.04l-.85-.02v-.85c0-1.9-.02-3.8-.07-5.71-1.92-.1-3.85-.12-5.78-.13h-.86v-.86c-.04-1.94-.06-3.88-.05-5.83-1.95 0-3.89-.02-5.83-.05l-.82-.01-.04-.83c-.07-1.94-.14-3.9-.15-5.84-1.9-.04-3.8-.05-5.7-.05h-.85l-.02-.85a170.8 170.8 0 0 1-.05-5.82c-1.95-.02-3.89-.03-5.83-.06l-.83-.01-.03-.83c-.07-1.94-.1-3.88-.1-5.84-1.94-.04-3.87-.05-5.8-.06h-.86l-.01-.86c-.01-1.93-.03-3.87-.07-5.8l-5.84-.03-.84-.01-.01-.85-.04-5.83c-1.94-.06-3.9-.04-5.86-.03h-.86v-.86A162 162 0 0 0 6.63.01L3.37 0Z'/%3E%3Cpath d='M.1.02C2.3-.01 4.48 0 6.66.02c.1 2.22.14 4.45.14 6.68 2.24-.02 4.48-.02 6.71.05 0 2.22.01 4.45.04 6.67-2.26-.02-4.51-.01-6.77 0-.01 31.42.07 62.83.04 94.25 2.23.02 4.46.03 6.68-.02-.02-2.22 0-4.44.01-6.66 2.23-.03 4.48-.23 6.69.17.36 2.2.16 4.44.1 6.65-2.18.03-4.37.05-6.56.02.02 2.23-.04 4.46-.18 6.68-4.48.03-8.97-.01-13.46 0-.18-13.23-.03-26.46-.08-39.69C.05 49.9-.05 24.96.11.03Z'/%3E%3Cpath d='m13.54 13.42 6.69.04c.05 2.21.06 4.43.08 6.65 2.22 0 4.44.02 6.66.07 0 2.22 0 4.45.11 6.67 2.23.04 4.45.05 6.68.07-.02 2.22 0 4.44.06 6.66 2.19 0 4.38.01 6.57.07 0 2.22.1 4.44.17 6.66 2.21.04 4.44.05 6.66.06-.01 2.22 0 4.44.04 6.66 2.22 0 4.44.03 6.65.15.07 2.2.09 4.38.09 6.58 2.22.06 4.44.07 6.66.06.02 2.22.04 4.45.04 6.68-2.25.12-4.5.1-6.75.04v-6.69c-2.25-.03-4.51-.02-6.77 0 .03-2.26.04-4.51 0-6.76h-6.7l.02-6.7c-2.26-.05-4.52-.04-6.77 0 0-2.26.01-4.52-.01-6.77h-6.7c-.03-2.24-.02-4.49-.04-6.73-2.25 0-4.49 0-6.73-.05.02-2.23.02-4.45 0-6.68-2.22-.02-4.44-.02-6.66 0-.07-2.25-.06-4.5-.05-6.74ZM60.7 60.5a93.2 93.2 0 0 1 6.69.14c.04 2.2.06 4.42.09 6.62 2.22 0 4.43.02 6.65.08-.01 2.22 0 4.45.04 6.68 2.22.03 4.45.05 6.67.05.08 4.48.07 8.95.02 13.43-8.93.1-17.86.1-26.78.12 0 2.2.02 4.4-.1 6.59-2.25.11-4.5.08-6.76.07-.06-4.5-.06-8.99 0-13.48 8.97-.05 17.95.03 26.92-.01.03-2.25.03-4.5 0-6.74-2.24-.02-4.5-.01-6.73-.05v-6.68a296.6 296.6 0 0 0-6.67 0c-.09-2.27-.09-4.54-.04-6.82ZM27 87.48c2.23-.02 4.46-.01 6.69 0 .08 2.3.18 4.62-.13 6.91-2.1.17-4.2.15-6.3.12 0 2.17-.05 4.34-.1 6.51-2.23.05-4.49.28-6.7-.14-.46-2.18-.24-4.44-.2-6.65l6.7-.01c0-2.25 0-4.5.04-6.74Zm6.56 6.92c2.3-.26 4.6-.18 6.9-.14.06 4.47.01 8.95.04 13.43 2.24 0 4.49 0 6.73.04.02 4.46-.04 8.92.03 13.38 4.5.07 9-.14 13.5.12.26 2.24.12 4.5-.07 6.75-4.52.02-9.03.04-13.55-.02 0-2.23-.01-4.45-.06-6.68-2.2 0-4.42-.03-6.63-.07-.07-4.46-.05-8.92-.1-13.37a270.1 270.1 0 0 1-6.67-.12c.24-4.45-.64-8.9-.12-13.33Z'/%3E%3Cpath d='M53.98 94.2a79.3 79.3 0 0 1 6.72.05c.02 4.45-.03 8.91.05 13.38 2.22.02 4.43.04 6.65.1.05 4.5.08 9 .01 13.5-2.21.05-4.44.1-6.65 0-.25-4.48-.04-8.97-.09-13.45-2.25-.05-4.5-.04-6.76-.06 0-4.5-.05-9.01.07-13.51Z'/%3E%3C/svg%3E%0A") 0 0, default;
|
||||
--cursor-pointer: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' fill='%2331274a' viewBox='0 0 128 128'%3E%3Cg clip-path='url(%23a)'%3E%3Cpath fill='%23fff' d='M29.14.42a426.8 426.8 0 0 0-.05 5.06l-.01.71-.7.03c-1.7.05-3.38.07-5.08.08-.09 17.14-.04 34.27-.04 51.4v.74l-.74.01c-1.42.02-2.86.03-4.29.07l-.77.01v-.77c.04-1.67.03-3.35-.01-5.01-5.81-.05-11.63-.08-17.44.02 0 5.79-.02 11.58 0 17.37 1.68.03 3.39.1 5.1-.01l.92-.07-.14.93c-.24 1.67-.08 3.36-.07 5.04 1.6.08 3.23.1 4.85.1h.7l.05.69c.27 3.58.14 7.17.2 10.77 1.67.07 3.35.1 5.03.11l.73.01v.73c.03 3.6.02 7.18.08 10.77 1.69.03 3.38.11 5.09.01l.86-.05-.07.85c-.28 3.6-.04 7.21-.07 10.81 1.65.03 3.29.06 4.93.07h.74v.73c.08 5.55.05 11.1.12 16.65 9.57.13 19.15.15 28.73.14 9.8-.02 19.6.06 29.41-.17-.15-5.53.34-11.06.11-16.59l-.02-.8.79.03c1.64.04 3.3.01 4.93-.04.06-5.5.07-11 .07-16.51v-.68l.67-.07c1.68-.16 3.36-.17 5.05-.16.04-6.16-.07-12.32.12-18.48v-.03c-.2-7.4-.06-14.81-.15-22.22-1.66.01-3.32 0-4.97-.03h-.72l-.02-.73a135.9 135.9 0 0 1-.02-4.91c-1.7-.05-3.4 0-5.1-.1l-.64-.03-.05-.66c-.12-1.7-.06-3.41-.09-5.13-3.6-.02-7.22.01-10.82-.04h-.73l-.01-.74c-.03-1.63-.05-3.26-.03-4.9-5.54-.29-11.1-.1-16.64-.16l-.71-.01-.03-.7c-.07-1.68-.1-3.37-.1-5.06-3.6-.02-7.2 0-10.8-.07l-.73-.02v-.72c-.08-7.46-.04-14.92-.06-22.38a371.76 371.76 0 0 0-5.03 0h-.77l.01-.76c.03-1.72.02-3.43-.14-5.13-3.81.01-7.62.02-11.43 0Z'/%3E%3Cpath d='M29.13.42c3.81.02 7.63.01 11.44 0 .18 1.92.17 3.84.14 5.75-3.88.04-7.75 0-11.63.04.02-1.93.02-3.86.05-5.79ZM23.3 6.3c1.93-.01 3.86 0 5.78-.09 0 21.32.04 42.63.02 63.95-1.94.04-3.88.04-5.83 0-.03-1.9-.03-3.82 0-5.73-1.94-.08-3.87-.07-5.8-.06a81.5 81.5 0 0 1 0-5.85c1.93-.07 3.86-.05 5.79-.08 0-17.38-.05-34.76.04-52.14Zm17.43 0c1.92-.02 3.84 0 5.77.01.02 7.7-.03 15.42.05 23.12 3.85.1 7.7.05 11.54.07 0 1.92 0 3.84.11 5.77 5.79.09 11.59-.14 17.37.16-.02 1.88-.01 3.76.03 5.64 3.85.07 7.71.02 11.57.04.02 1.93-.1 3.87.1 5.8 1.92.16 3.84.06 5.76.12-.03 1.88-.01 3.76.04 5.64 1.9.03 3.8.05 5.7.03.09 7.42-.06 14.83.15 22.23-.2 6.17-.08 12.34-.12 18.5a43.63 43.63 0 0 0-5.72.22c0 5.73-.01 11.47-.07 17.2-1.9.06-3.82.12-5.72.03-.21-5.83-.11-11.67-.06-17.51 1.92.02 3.84.02 5.76 0L93 52.72c-1.92-.03-3.83-.02-5.75 0-.1-1.89.02-3.78-.13-5.66-1.9-.37-3.85-.15-5.77-.15-.04 5.8.07 11.62-.04 17.44h-5.7c-.13-7.75 0-15.5-.04-23.26-3.89-.02-7.78 0-11.66 0 0 5.81.06 11.62 0 17.43-1.93.04-3.86.04-5.78 0-.04-7.75-.04-15.5.05-23.24-3.89-.02-7.78-.03-11.67.02-.04 7.74.03 15.48 0 23.22-1.94.05-3.9.06-5.84 0 0-17.4.02-34.8.05-52.21ZM0 52.76c5.82-.1 11.64-.06 17.45-.01.04 1.92.07 3.84.02 5.77-3.86.1-7.71.02-11.57.05-.14 3.84.2 7.7-.05 11.53-1.95.22-3.9.07-5.85.03V52.76Zm6 17.47c1.87-.3 3.77-.18 5.65-.13.04 1.94.04 3.88.02 5.82 1.95.01 3.88 0 5.82.03.05 3.87 0 7.73.03 11.6 1.91-.02 3.83-.01 5.75.01-.03 3.88.25 7.79-.14 11.64-1.9.17-3.79.04-5.67 0-.06-3.82-.05-7.65-.09-11.48-1.92-.01-3.84-.05-5.76-.13-.06-3.81.13-7.63-.22-11.44a115 115 0 0 1-5.57-.12c0-1.94-.26-3.9.18-5.8Z'/%3E%3Cpath d='M23.39 99.23c1.9-.15 3.8-.06 5.7-.05.06 3.86.01 7.71.02 11.57 1.94-.01 3.88-.01 5.82.06.03 3.85-.04 7.71.02 11.57 15.46.04 30.92.03 46.38.02.06-3.86-.01-7.72.03-11.58 1.98-.03 3.95-.05 5.93.06.32 5.78-.25 11.57-.09 17.37-9.8.23-19.6.15-29.4.16-9.59.01-19.16 0-28.73-.13-.08-5.8-.04-11.59-.13-17.37-1.89 0-3.78-.04-5.67-.07.03-3.87-.28-7.77.12-11.61Z'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='a'%3E%3Cpath fill='%23fff' d='M0 0h128v128H0z'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E") 8 0, pointer;
|
||||
|
|
|
@ -9,3 +9,162 @@ const Tag = href ? 'a' : 'div';
|
|||
{Array.from({ length: 6 }, (_, i) => <span class="group" style={`--i: ${i};`} id={i === 0 ? 'not-marquee-label' : undefined} aria-hidden={i > 0 ? 'true' : undefined}>{items.map(item => <span>{item}</span>)}</span>)}
|
||||
</Tag>
|
||||
</not-marquee>
|
||||
|
||||
<!-- Blocking, rehydrate from localStorage immediately -->
|
||||
<script global>
|
||||
document.getElementById('marquee-pause').checked = (localStorage.getItem('astro:marquee-paused') || 'false') === 'true';
|
||||
</script>
|
||||
|
||||
<script type="module" hoist>
|
||||
import "/src/scripts/marquee.ts";
|
||||
</script>
|
||||
|
||||
<style>
|
||||
not-marquee {
|
||||
--color: var(--color-midnight);
|
||||
--height: 2rem;
|
||||
--speed: 25;
|
||||
--gap: var(--size-1000);
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
height: var(--height);
|
||||
overflow: hidden;
|
||||
|
||||
border-top: 1px solid var(--color);
|
||||
margin-top: -1px;
|
||||
border-bottom: 1px solid var(--color);
|
||||
font-family: var(--font-display);
|
||||
text-transform: uppercase;
|
||||
font-size: 0.75em;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
background: white;
|
||||
z-index: 3;
|
||||
|
||||
}
|
||||
|
||||
not-marquee::before,
|
||||
not-marquee::after {
|
||||
content: "";
|
||||
width: var(--gap);
|
||||
height: var(--height);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: var(--right, auto);
|
||||
bottom: 0;
|
||||
left: var(--left, auto);
|
||||
background: linear-gradient(var(--dir, to right), white, white 5%, rgba(255, 255, 255, 0));
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
not-marquee::before {
|
||||
--left: calc(var(--height) - 4px);
|
||||
--dir: to right;
|
||||
}
|
||||
not-marquee::after {
|
||||
--right: 0;
|
||||
--dir: to left;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
--size: var(--height);
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
border-radius: 0;
|
||||
z-index: 2;
|
||||
background: white;
|
||||
margin-top: -1px;
|
||||
margin-left: -1px;
|
||||
border: 1px solid var(--color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:hover,
|
||||
input[type="checkbox"]:focus {
|
||||
background: var(--color-dusk);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:active {
|
||||
background: var(--color-purple);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:hover::before,
|
||||
input[type="checkbox"]:focus::before,
|
||||
input[type="checkbox"]:active::before {
|
||||
filter: saturate(0) brightness(0) invert(1);
|
||||
}
|
||||
|
||||
input[type="checkbox"]::before {
|
||||
content: "";
|
||||
width: calc(var(--size) * 0.75);
|
||||
height: calc(var(--size) * 0.75);
|
||||
}
|
||||
|
||||
input[type="checkbox"]::before {
|
||||
/* Pause */
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M14 19h4V5h-4M6 19h4V5H6v14z' fill='%2331274a'%3E%3C/path%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked::before {
|
||||
/* Play */
|
||||
background-position: -1px center;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M8 5.14v14l11-7l-11-7z' fill='%2331274a'%3E%3C/path%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked ~ .track,
|
||||
.track:hover {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
|
||||
.track {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
color: var(--color);
|
||||
transition: color 300ms cubic-bezier(0.23, 1, 0.320, 1);
|
||||
}
|
||||
|
||||
a.track:hover,
|
||||
a.track:focus {
|
||||
color: var(--color-purple);
|
||||
}
|
||||
|
||||
a.track:active {
|
||||
color: var(--color-blue);
|
||||
}
|
||||
|
||||
.group {
|
||||
position: absolute;
|
||||
display: block;
|
||||
animation: marquee calc(var(--speed) * 1s) linear infinite;
|
||||
animation-play-state: inherit;
|
||||
user-select: none;
|
||||
padding-left: var(--gap);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.track {
|
||||
animation-play-state: paused;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.group > span + span {
|
||||
padding-left: var(--gap);
|
||||
}
|
||||
|
||||
@keyframes marquee {
|
||||
from { transform: translateX(calc(100% * var(--i, 0))) }
|
||||
to { transform: translateX(calc(100% * calc(var(--i, 0) - 1))) }
|
||||
}
|
||||
</style>
|
|
@ -1,28 +1,20 @@
|
|||
---
|
||||
import { smartypants } from 'smartypants';
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
description: string;
|
||||
canonicalURL: URL | string,
|
||||
title?: string;
|
||||
description?: string;
|
||||
canonicalURL?: URL | string
|
||||
image?: string;
|
||||
}
|
||||
const { title, description, canonicalURL } = Astro.props;
|
||||
const { canonicalURL = Astro.request.canonicalURL } = Astro.props;
|
||||
const image = new URL(Astro.props.image || './social.png', Astro.site);
|
||||
---
|
||||
const description = Astro.props.description || 'Astro is a new kind of static site builder for the modern web. Powerful developer experience meets lightweight output.';
|
||||
|
||||
<!-- Blocking script -->
|
||||
<script>
|
||||
const marqueePaused = (localStorage.getItem('astro:marquee-paused') || 'false') === 'true';
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const checkbox = document.querySelector('#marquee-pause');
|
||||
if(checkbox) {
|
||||
checkbox.checked = marqueePaused;
|
||||
document.body.classList.add('js');
|
||||
}
|
||||
});
|
||||
if ('paintWorklet' in CSS) {
|
||||
CSS.paintWorklet.addModule('/pixel.worklet.js');
|
||||
}
|
||||
</script>
|
||||
const title = [Astro.props.title, 'Astro']
|
||||
.filter(Boolean)
|
||||
.join(' | ')
|
||||
---
|
||||
|
||||
<!-- Global Metadata -->
|
||||
<meta charset="utf-8" />
|
||||
|
@ -34,11 +26,10 @@ const image = new URL(Astro.props.image || './social.png', Astro.site);
|
|||
<link rel="alternate" type="application/rss+xml" href="/rss.xml" title="RSS" />
|
||||
|
||||
<!-- Preload -->
|
||||
<link rel="preload" as="style" href="/styles/sanitize.css">
|
||||
<link rel="preload" as="style" href="/styles/main.css">
|
||||
<slot name="preload" />
|
||||
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>{title}</title>
|
||||
<title set:html={smartypants(title, 1)}></title>
|
||||
<meta name="title" content={title} />
|
||||
<meta name="description" content={description} />
|
||||
<link rel="canonical" href={canonicalURL}/>
|
||||
|
@ -58,5 +49,4 @@ const image = new URL(Astro.props.image || './social.png', Astro.site);
|
|||
<meta property="twitter:image" content={image} />
|
||||
|
||||
<!-- Assets -->
|
||||
<link rel="stylesheet" href="/styles/sanitize.css" />
|
||||
<link rel="stylesheet" href="/styles/main.css" />
|
||||
<slot name="assets" />
|
|
@ -1,26 +0,0 @@
|
|||
---
|
||||
import { Sprite } from 'astro-icon';
|
||||
import Header from '../components/Header.astro';
|
||||
import Scripts from '../components/Scripts.astro';
|
||||
|
||||
const { wrapper: Wrapper = Fragment, container = false } = Astro.props;
|
||||
---
|
||||
|
||||
<Sprite.Provider>
|
||||
<Header>
|
||||
<slot name="nav" />
|
||||
</Header>
|
||||
|
||||
<div id="root">
|
||||
<Wrapper>
|
||||
<slot name="start" />
|
||||
<main id="content" class:list={{ container }}>
|
||||
<slot />
|
||||
</main>
|
||||
</Wrapper>
|
||||
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
</Sprite.Provider>
|
||||
|
||||
<Scripts />
|
|
@ -5,7 +5,7 @@
|
|||
<div class="logo">
|
||||
<slot name="logo" />
|
||||
</div>
|
||||
<blockquote class="container">
|
||||
<blockquote class="astro-container container">
|
||||
<p class=""><slot name="quote" /></p>
|
||||
<cite class="head-sm"><slot name="cite" /></cite>
|
||||
</blockquote>
|
||||
|
|
|
@ -2,6 +2,42 @@
|
|||
const { cols = 2 } = Astro.props;
|
||||
---
|
||||
|
||||
<ul class="checklist" style={`--cols: ${cols};`} role="list">
|
||||
<ul style={`--cols: ${cols};`} role="list">
|
||||
<slot />
|
||||
</ul>
|
||||
|
||||
<style>
|
||||
ul {
|
||||
font-size: var(--size-500);
|
||||
--marker-size: 3rem;
|
||||
display: grid;
|
||||
gap: 0.75rem;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
max-width: 72rem;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
@media (min-width: 24rem) {
|
||||
ul {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 40rem) {
|
||||
ul {
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 52rem) {
|
||||
ul {
|
||||
grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -5,12 +5,12 @@ const Wrapper = href ? 'a' : Fragment;
|
|||
const wrapperProps = href ? { href, target: '_blank', rel: 'noopener noreferrer' } : {};
|
||||
---
|
||||
|
||||
<li class="checklist-item" role="listitem">
|
||||
<li role="listitem">
|
||||
<Wrapper {...wrapperProps}>
|
||||
<span class="checklist-marker">
|
||||
<span class="marker">
|
||||
<slot name="icon" />
|
||||
</span>
|
||||
<span class="checklist-text"><slot /></span>
|
||||
<span class="text"><slot /></span>
|
||||
<Sprite aria-hidden="true" class="arrow" pack="mdi" name="arrow-right" size="1em" />
|
||||
</Wrapper>
|
||||
</li>
|
||||
|
@ -22,11 +22,11 @@ a {
|
|||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
.checklist-marker {
|
||||
.marker {
|
||||
transition: transform 200ms cubic-bezier(0.23, 1, 0.320, 1);
|
||||
transition-property: transform, background, color;
|
||||
}
|
||||
a:is(:hover, :focus) .checklist-marker {
|
||||
a:is(:hover, :focus) .marker {
|
||||
color: var(--color-dawn);
|
||||
background: var(--color-purple);
|
||||
transform: scale(1.10);
|
||||
|
@ -40,4 +40,23 @@ a:is(:hover, :focus) .arrow {
|
|||
transform: translateX(0.25em);
|
||||
opacity: 1;
|
||||
}
|
||||
.marker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: var(--marker-size);
|
||||
height: var(--marker-size);
|
||||
background: var(--color-dawn);
|
||||
color: var(--color-midnight);
|
||||
border-radius: 50%;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
.text {
|
||||
font-size: var(--size-600);
|
||||
}
|
||||
@media (min-width: 24rem) {
|
||||
li {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -3,9 +3,15 @@ import ContributorAvatar from './ContributorAvatar.astro';
|
|||
import ArrowLink from '../components/ArrowLink.astro';
|
||||
import contributors from '../data/contributors.json';
|
||||
|
||||
export interface Props {
|
||||
id?: string;
|
||||
}
|
||||
|
||||
const { id } = Astro.props as Props;
|
||||
|
||||
const {staff, l3, l2, l1} = contributors;
|
||||
---
|
||||
<ul class="avatar-list">
|
||||
<ul class="avatar-list" {id}>
|
||||
{staff.map(obj => <li><ContributorAvatar size={72} obj={obj} type="staff" /></li>)}
|
||||
{l3.map(obj => <li><ContributorAvatar size={72} obj={obj} type="l3" /></li>)}
|
||||
{l2.map(obj => <li><ContributorAvatar size={72} obj={obj} type="l2" /></li>)}
|
||||
|
|
|
@ -28,12 +28,13 @@ const YYYY = new Date().getFullYear();
|
|||
</Quote>
|
||||
)}
|
||||
|
||||
<div class="container content">
|
||||
<div class="astro-container container content">
|
||||
<ul class="links">
|
||||
<li>© {YYYY} The Astro Technology Company</li>
|
||||
<li><a href="/about">About</a></li>
|
||||
<li><a href="/company">We're Hiring!</a></li>
|
||||
<li><a href="/blog">Blog</a></li>
|
||||
<li><a href="/press">Press</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
---
|
||||
import { Sprite } from 'astro-icon';
|
||||
import { mentions } from '../mentions.ts';
|
||||
const { name } = Astro.props;
|
||||
|
||||
|
|
|
@ -11,11 +11,11 @@ const items = [
|
|||
]
|
||||
---
|
||||
|
||||
<nav id="nav" class={`main ${invert ? 'invert' : ''} ${marginBottom ? 'margin-bottom' : ''}`.trim()} style={`--offset: 2.5;`}>
|
||||
<ul class="container" role="list">
|
||||
<nav id="nav" class={`main ${invert ? 'dark' : ''} ${marginBottom ? 'margin-bottom' : ''}`.trim()} style={`--offset: 2.5;`}>
|
||||
<ul class="astro-container container" role="list">
|
||||
<li class="logo">
|
||||
<a href="/">
|
||||
<h1 class="visually-hidden">Astro</h1>
|
||||
<a href="/" id="navlogo">
|
||||
<h1 class="visually-hidden sr-only">Astro</h1>
|
||||
<Sprite class="logomark" name="logo" size="3em" />
|
||||
<Sprite class="wordmark" name="wordmark" height="3.5em" width="6em" />
|
||||
</a>
|
||||
|
@ -38,3 +38,168 @@ const items = [
|
|||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<script type="module" hoist>
|
||||
import "/src/scripts/nav.ts";
|
||||
</script>
|
||||
|
||||
<style>
|
||||
nav {
|
||||
--offset-height: calc(var(--offset) * 1rem);
|
||||
width: 100%;
|
||||
position: sticky;
|
||||
top: calc((var(--offset-height) * -1) - 1px);
|
||||
margin-top: -2rem;
|
||||
padding: 0.5rem 0;
|
||||
background: linear-gradient(0deg, rgba(var(--color-tan-rgb), 0.7), rgba(var(--color-tan-rgb), 1));
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
backdrop-filter: blur(10px);
|
||||
z-index: 2;
|
||||
}
|
||||
nav.margin-bottom {
|
||||
margin-bottom: -4.5rem;
|
||||
}
|
||||
nav.dark {
|
||||
background: transparent;
|
||||
color: white;
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
nav.dark a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
nav::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: var(--offset-height);
|
||||
z-index: -2;
|
||||
}
|
||||
nav.dark::before {
|
||||
margin-top: -0.5rem;
|
||||
}
|
||||
|
||||
nav::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: var(--offset-height);
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
box-shadow: var(--shadow-md);
|
||||
opacity: 0;
|
||||
transition-property: opacity;
|
||||
transition-duration: 200ms;
|
||||
transition-timing-function: cubic-bezier(0.23, 1, 0.320, 1);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
nav[stuck]::after {
|
||||
opacity: 0.5;
|
||||
transition-duration: 600ms;
|
||||
}
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.33rem;
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
li {
|
||||
color: var(--color-dusk);
|
||||
font-family: var(--font-display);
|
||||
font-weight: 400;
|
||||
font-size: var(--size-500);
|
||||
}
|
||||
nav.dark li {
|
||||
color: white;
|
||||
}
|
||||
li + li {
|
||||
margin-left: 0;
|
||||
}
|
||||
[aria-current="page"] {
|
||||
font-weight: 700;
|
||||
}
|
||||
.logo {
|
||||
font-size: 1rem;
|
||||
margin-right: auto;
|
||||
}
|
||||
.logo a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--color-midnight);
|
||||
}
|
||||
.logo a:hover,
|
||||
.logo a:focus {
|
||||
color: var(--color-midnight);
|
||||
}
|
||||
.logo a:active {
|
||||
color: var(--color-midnight);
|
||||
}
|
||||
.logo :global(svg) {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
.logomark {
|
||||
color: inherit;
|
||||
}
|
||||
nav.dark .logo :global(svg) {
|
||||
color: white;
|
||||
fill: white;
|
||||
}
|
||||
.wordmark {
|
||||
display: none;
|
||||
color: inherit;
|
||||
margin-top: -0.5rem;
|
||||
}
|
||||
.hidden-mobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 52rem) {
|
||||
nav {
|
||||
/* height: calc(2px + 4.5rem); */
|
||||
}
|
||||
.logo :global(svg) {
|
||||
transform: scale(1);
|
||||
}
|
||||
.wordmark {
|
||||
display: block;
|
||||
}
|
||||
.hidden-mobile {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
a {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
color: var(--color-midnight);
|
||||
text-decoration: none;
|
||||
transition: all 200ms cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||
transition-property: transform, color;
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
a:focus,
|
||||
a:hover {
|
||||
color: var(--color-purple);
|
||||
}
|
||||
a:active {
|
||||
color: var(--color-blue);
|
||||
}
|
||||
|
||||
.icon a :global(svg) {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
.icon a:focus :global(svg),
|
||||
.icon a:hover :global(svg) {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
[astro-icon="logo"] {
|
||||
margin-right: 0.25em;
|
||||
transform: translateY(0.5em);
|
||||
}
|
||||
</style>
|
38
smoke/astro.build-main/src/components/Noscript.astro
Normal file
|
@ -0,0 +1,38 @@
|
|||
<noscript></noscript>
|
||||
|
||||
<style>
|
||||
noscript {
|
||||
order: -1;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--size-600);
|
||||
text-align: center;
|
||||
color: var(--color-midnight);
|
||||
background: linear-gradient(to bottom, var(--color-tan), white);
|
||||
}
|
||||
noscript::before {
|
||||
--size: var(--size-1000);
|
||||
padding-top: var(--size);
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
content: 'You need to enable JavaScript to view this site.';
|
||||
background-size: var(--size);
|
||||
background-position: center top;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 140 140'%3E%3Cg fill='%23514375'%3E%3Cpath d='M129.7 100v20h-10v-20z'/%3E%3Cpath d='M119.69 100h20v10h-20zM10 100v20h10v-20z'/%3E%3Cpath d='M20 100H0v10h20zm0-90H0v10h20z'/%3E%3Cpath d='M20 20V0H10v20zm79.69 30h20v10h-20zm-39.21 0h20v10h-20zM29.73 20h80v10h-80zm-9.97 50h99.93v10H19.76zm10 10h79.93v10H29.76zm-.03 10h20v10h-20zm30.75 0h20v10h-20zm29.21 0h20v10h-20zM19.73 30h100v10h-100zm0 10h100v10h-100zm0 20h100v10h-100zm0-10h20v10h-20zM120 10h20v10h-20z'/%3E%3Cpath d='M120 20V0h10v20z'/%3E%3C/g%3E%3C/svg%3E%0A");
|
||||
}
|
||||
noscript::after {
|
||||
--size: var(--size-1000);
|
||||
content: "Just kidding—you're going to love Astro!";
|
||||
font-size: 0.75em;
|
||||
padding-bottom: var(--size);
|
||||
background-size: var(--size);
|
||||
background-position: 50% 100%;
|
||||
background-image: url("data:image/svg+xml,%3Csvg width='140' height='141' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23af43ff' d='M85 80.325v-20h10v20zM45 80.325v-20h10v20zM65 40.325h10v60H65z'/%3E%3Cpath fill='%23af43ff' d='M55 80.325h30v10H55z'/%3E%3C/svg%3E");
|
||||
animation: bounce 1s steps(4) alternate-reverse infinite;
|
||||
}
|
||||
</style>
|
|
@ -26,7 +26,6 @@ const { type = 'tip', title } = Astro.props;
|
|||
|
||||
background: var(--color-dawn);
|
||||
color: var(--color-midnight);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
@media (min-width: 64rem) {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
const { class: className, background = 'color-tan', offset = 0, size = "lg", pad = 1 } = Astro.props;
|
||||
const { class: className, background = 'color-tan', offset = 0, size = "lg", elevation = "xl", pad = 1 } = Astro.props;
|
||||
let style = `--pad: ${pad}; `;
|
||||
if (offset !== 0) {
|
||||
style += `--offset-block: ${offset};`
|
||||
}
|
||||
---
|
||||
|
||||
<div class="container" style={style}>
|
||||
<article class={`panel elevation-xl size-${size} ${className}`} style={`--background: ${background};`}>
|
||||
<div class="astro-container px-2" style={style}>
|
||||
<article class={`panel elevation-${elevation} size-${size} ${className}`} style={`--background: ${background};`}>
|
||||
{Astro.slots.title && <div class="title">
|
||||
<slot name="title" />
|
||||
</div>}
|
||||
|
@ -16,7 +16,7 @@ if (offset !== 0) {
|
|||
</div>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
.astro-container {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-top: calc(var(--offset-block, 0) * -1rem);
|
||||
|
|
|
@ -6,6 +6,13 @@ const { variant = 'primary' } = Astro.props;
|
|||
const { before, after } = Astro.slots;
|
||||
---
|
||||
|
||||
<!-- Blocking script -->
|
||||
<script hoist>
|
||||
if ('paintWorklet' in CSS) {
|
||||
CSS.paintWorklet.addModule('/pixel.worklet.js');
|
||||
}
|
||||
</script>
|
||||
|
||||
<span class={`link pixel variant-${variant} ${before ? 'has-before' : ''} ${after ? 'has-after' : ''} ${className}`.trim()}>
|
||||
<a {href}>
|
||||
<slot name="before" />
|
||||
|
@ -15,6 +22,72 @@ const { before, after } = Astro.slots;
|
|||
</span>
|
||||
|
||||
<style>
|
||||
.pixel {
|
||||
--border-radius: 8;
|
||||
--pixel-size: 4;
|
||||
--background: var(--gradient-pop-1);
|
||||
position: relative;
|
||||
border-radius: calc(var(--border-radius) * 1px);
|
||||
}
|
||||
.pixel::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: calc(var(--pixel-size) * 1px);
|
||||
right: 0;
|
||||
bottom: calc(var(--pixel-size) * 1px);
|
||||
left: 0;
|
||||
background: var(--background);
|
||||
z-index: -1;
|
||||
}
|
||||
.pixel::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: calc(var(--pixel-size) * 1px);
|
||||
bottom: 0;
|
||||
left: calc(var(--pixel-size) * 1px);
|
||||
background: var(--background);
|
||||
z-index: -1;
|
||||
}
|
||||
.pixel.variant-outline {
|
||||
background: rgba(255, 255, 255, 0);
|
||||
border-radius: 0;
|
||||
}
|
||||
.pixel.variant-outline::before {
|
||||
background: rgba(255, 255, 255, 0);
|
||||
border: calc(var(--pixel-size) * 1px) solid var(--background);
|
||||
border-top: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.pixel.variant-outline::after {
|
||||
background: rgba(255, 255, 255, 0);
|
||||
border: calc(var(--pixel-size) * 1px) solid var(--background);
|
||||
border-right: 0;
|
||||
border-left: 0;
|
||||
}
|
||||
@supports (background: paint(pixel)) {
|
||||
:global(.js) .pixel {
|
||||
background: none !important;
|
||||
}
|
||||
:global(.js) .pixel::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
z-index: -1;
|
||||
overflow: hidden;
|
||||
border-radius: 0;
|
||||
background: var(--background);
|
||||
-webkit-mask-image: paint(pixel);
|
||||
mask-image: paint(pixel);
|
||||
}
|
||||
:global(.js) .pixel::after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
.link {
|
||||
--border-radius: 8;
|
||||
--duration: 200ms;
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
{Astro.request.url.pathname === '/' && <noscript></noscript>}
|
||||
<script type="module" hoist>
|
||||
import "../scripts/nav.ts";
|
||||
</script>
|
||||
<script type="module" src="/scripts/defer.js"></script>
|
||||
<script type="module">
|
||||
const checkbox = document.querySelector('#marquee-pause');
|
||||
if(checkbox) {
|
||||
function onChange(element) {
|
||||
const paused = element.checked;
|
||||
localStorage.setItem('astro:marquee-paused', `${paused}`);
|
||||
}
|
||||
checkbox.addEventListener('change', ({ target }) => onChange(target))
|
||||
checkbox.addEventListener('keydown', ({ target, key }) => {
|
||||
if (key !== 'Enter') return;
|
||||
onChange(target);
|
||||
});
|
||||
}
|
||||
</script>
|
|
@ -1 +1,44 @@
|
|||
<a href="#content" class="skip-link">Skip to main content</a>
|
||||
<a href="#content">Skip to main content</a>
|
||||
|
||||
<style>
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
overflow-x: hidden;
|
||||
text-align: center;
|
||||
|
||||
background-color: white;
|
||||
border-bottom: 1px solid transparent;
|
||||
font-family: var(--font-display);
|
||||
text-transform: uppercase;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
background: white;
|
||||
z-index: 5;
|
||||
|
||||
/* Visually hidden */
|
||||
clip: rect(0 0 0 0);
|
||||
clip-path: inset(50%);
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
width: 1px;
|
||||
}
|
||||
a:focus {
|
||||
width: 100vw;
|
||||
height: 48px;
|
||||
position: fixed;
|
||||
clip: initial;
|
||||
clip-path: initial;
|
||||
|
||||
background: var(--color-purple);
|
||||
color: white;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,5 @@
|
|||
<article class="bg-dawn shadow-lg px-4 py-4 text-center rounded-lg sm:px-6 lg:px-8">
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<slot />
|
||||
</div>
|
||||
</article>
|
|
@ -0,0 +1,3 @@
|
|||
<section class="prose mx-auto">
|
||||
<slot />
|
||||
</section>
|
|
@ -0,0 +1,10 @@
|
|||
<div class="max-w-7xl mx-auto">
|
||||
<div class="sm:text-center">
|
||||
<h1 class="text-3xl md:text-3xl font-bold font-display text-gradient">
|
||||
<slot name="title" />
|
||||
</h1>
|
||||
<div class="max-w-2xl mt-5 mx-auto">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -68,7 +68,7 @@ h2.title {
|
|||
flex-grow: 2;
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 52rem) {
|
||||
@media (min-width: 50rem) {
|
||||
.authors {
|
||||
width: initial;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ const { tweet: { title, href } } = Astro.props;
|
|||
---
|
||||
|
||||
<section class="outro">
|
||||
<div class="container">
|
||||
<div class="astro-container container">
|
||||
<div class="content">
|
||||
<a class="return" href="/blog">
|
||||
<Sprite pack="mdi" name="arrow-left" size="32" aria-hidden="true" />
|
||||
|
@ -21,7 +21,7 @@ const { tweet: { title, href } } = Astro.props;
|
|||
|
||||
<style>
|
||||
.outro {
|
||||
padding: 8rem 0 2rem;
|
||||
padding: 4rem 0 0;
|
||||
width: 100%;
|
||||
}
|
||||
.content {
|
||||
|
@ -50,4 +50,9 @@ const { tweet: { title, href } } = Astro.props;
|
|||
padding: 0.25em 0.5em;
|
||||
gap: 0.25em;
|
||||
}
|
||||
@media (min-width: 52rem) {
|
||||
.outro {
|
||||
padding: 8rem 0 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
---
|
||||
import Section from './Section.astro';
|
||||
import Title from './Title.astro';
|
||||
import Panel from '../Panel.astro';
|
||||
---
|
||||
|
||||
<Section {...Astro.props}>
|
||||
<Panel background="var(--gradient-pop-4)">
|
||||
<div class="container">
|
||||
<div class="astro-container container">
|
||||
<div class="content">
|
||||
<h3 class="head-md"><slot name="title" /></h3>
|
||||
<div class="body">
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
---
|
||||
import Panel from '../Panel.astro';
|
||||
import Checklist from '../Checklist.astro';
|
||||
---
|
||||
|
||||
<section>
|
||||
<Panel background="var(--gradient-pop-3)">
|
||||
<Fragment slot="title">
|
||||
<h3 class="head-md">Batteries Included.</h3>
|
||||
<p>Astro does the heavy lifting in the background—no plugins required.</p>
|
||||
</Fragment>
|
||||
|
||||
<Checklist>
|
||||
<li>Markdown Support</li>
|
||||
<li>TypeScript</li>
|
||||
<li>CSS Modules</li>
|
||||
<li>PostCSS, Sass, Less, Stylus</li>
|
||||
<li>Built-in SEO</li>
|
||||
<li>Sitemaps</li>
|
||||
<li>RSS Feeds</li>
|
||||
<li>Pagination</li>
|
||||
</Checklist>
|
||||
</Panel>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
section {
|
||||
background: var(--color-tan);
|
||||
padding-bottom: 20rem;
|
||||
}
|
||||
</style>
|
|
@ -3,7 +3,7 @@ import Section from './Section.astro';
|
|||
const { reverse, gradient = false } = Astro.props;
|
||||
---
|
||||
<Section pad={2} class={"demo" + (gradient ? ' gradient' : '')}>
|
||||
<div class="container">
|
||||
<div class="astro-container">
|
||||
<div class="content">
|
||||
<h3 class="head-md title"><slot name="title" /></h3>
|
||||
<slot />
|
||||
|
@ -25,7 +25,7 @@ const { reverse, gradient = false } = Astro.props;
|
|||
.gradient {
|
||||
background: var(--color-tan) linear-gradient(180deg, #E5DAEE 0%, rgba(255, 255, 255, 0) 100%);
|
||||
}
|
||||
.container {
|
||||
.astro-container {
|
||||
display: grid;
|
||||
gap: 4rem;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ const { reverse, gradient = false } = Astro.props;
|
|||
.title {
|
||||
margin-top: -2.5ex;
|
||||
}
|
||||
.container {
|
||||
.astro-container {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
.content {
|
||||
|
|
|
@ -8,10 +8,10 @@ import Grid from './Grid.astro';
|
|||
<div class="blob-c" />
|
||||
</div>
|
||||
<Grid />
|
||||
<div class="container content">
|
||||
<div class="astro-container container content">
|
||||
<h2 class="text-gradient"><slot name="title" /></h2>
|
||||
<p><slot name="tagline" /></p>
|
||||
<div class="cta container">
|
||||
<div class="cta astro-container container">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,7 +10,7 @@ const rows = [
|
|||
---
|
||||
|
||||
<Section id="frameworks">
|
||||
<div class="container content">
|
||||
<div class="astro-container container content">
|
||||
<h3 class="head-md title"><slot name="title" /></h3>
|
||||
<div class="body">
|
||||
<slot />
|
||||
|
|
|
@ -11,7 +11,7 @@ const tweet = {
|
|||
|
||||
<Section class="performance" style="--background: var(--gradient-pop-4);">
|
||||
<Starfield height={48} />
|
||||
<div class="container">
|
||||
<div class="astro-container">
|
||||
<div class="content">
|
||||
<h3 class="head-md"><slot name="title" /></h3>
|
||||
<div class="body">
|
||||
|
@ -59,7 +59,7 @@ const tweet = {
|
|||
.content {
|
||||
color: white;
|
||||
}
|
||||
.container {
|
||||
.astro-container {
|
||||
display: grid;
|
||||
gap: 4rem;
|
||||
padding: 0;
|
||||
|
@ -141,7 +141,7 @@ const tweet = {
|
|||
.data {
|
||||
order: initial;
|
||||
}
|
||||
.container {
|
||||
.astro-container {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ const { pad = 1, background, blobs = true, color } = Astro.props;
|
|||
<div class="logo">
|
||||
<slot name="logo" />
|
||||
</div>
|
||||
<blockquote class="container">
|
||||
<blockquote class="astro-container container">
|
||||
<p class="head-md"><slot name="quote" /></p>
|
||||
<cite class="head-md"><slot name="cite" /></cite>
|
||||
</blockquote>
|
||||
|
|
|
@ -30,7 +30,7 @@ const individuals = users.filter(user => isUser(user)).map(user => getUser(user)
|
|||
---
|
||||
|
||||
<Section class="sponsor-section" pad={2} {...Astro.props}>
|
||||
<div class="container">
|
||||
<div class="astro-container">
|
||||
<h3 class="head-sm title"><slot name="title" /></h3>
|
||||
<ul class="sponsors exclusive">
|
||||
{exclusive.map(sponsor => (
|
||||
|
@ -65,9 +65,6 @@ const individuals = users.filter(user => isUser(user)).map(user => getUser(user)
|
|||
.sponsor-section {
|
||||
padding-top: calc(var(--size-1000) * var(--pad, 1));
|
||||
--background: linear-gradient(to bottom, var(--color-tan) 0%, #E8ADB7 100%);
|
||||
}
|
||||
.container {
|
||||
|
||||
}
|
||||
.title {
|
||||
text-align: center;
|
||||
|
|
68
smoke/astro.build-main/src/layouts/Base.astro
Normal file
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
import { Sprite } from 'astro-icon';
|
||||
import BaseHead from '../components/BaseHead.astro';
|
||||
import SkipLink from '../components/SkipLink.astro';
|
||||
import type { Props as BaseHeadProps } from '../components/BaseHead.astro';
|
||||
|
||||
export interface Props {
|
||||
wrapper?: any;
|
||||
meta: BaseHeadProps;
|
||||
container?: boolean;
|
||||
routeId?: string;
|
||||
}
|
||||
|
||||
const { wrapper: Wrapper = Fragment, meta, container = false, routeId } = Astro.props;
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<BaseHead {...meta}>
|
||||
<Fragment slot="preload">
|
||||
<link rel="preload" as="style" href="/styles/sanitize.css">
|
||||
<link rel="preload" as="style" href="/styles/main.css">
|
||||
</Fragment>
|
||||
|
||||
<Fragment slot="assets">
|
||||
<link rel="stylesheet" href="/styles/sanitize.css" />
|
||||
<link rel="stylesheet" href="/styles/main.css" />
|
||||
</Fragment>
|
||||
</BaseHead>
|
||||
|
||||
<slot name="head" />
|
||||
|
||||
<script>
|
||||
document.body.classList.add('js');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<Sprite.Provider>
|
||||
<slot name="banner" />
|
||||
|
||||
<SkipLink />
|
||||
<slot name="nav" />
|
||||
|
||||
<Wrapper>
|
||||
<slot name="start" />
|
||||
<main id="content" data-route-id={routeId} class={container ? "astro-container container": ""}>
|
||||
<slot />
|
||||
</main>
|
||||
</Wrapper>
|
||||
|
||||
<slot name="footer" />
|
||||
</Sprite.Provider>
|
||||
|
||||
<script type="module" hoist>
|
||||
import "/src/scripts/defer.ts";
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style global>
|
||||
:root {
|
||||
scroll-padding-top: 10rem;
|
||||
}
|
||||
main {
|
||||
max-width: 100vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
61
smoke/astro.build-main/src/layouts/Content.astro
Normal file
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
import { Sprite } from 'astro-icon';
|
||||
import BaseHead from '../components/BaseHead.astro';
|
||||
import SkipLink from '../components/SkipLink.astro';
|
||||
import type { Props as BaseHeadProps } from '../components/BaseHead.astro';
|
||||
import '../styles/fonts.css';
|
||||
import '../styles/variables.css';
|
||||
import '../styles/tailwind.css';
|
||||
|
||||
export interface Props {
|
||||
meta: BaseHeadProps;
|
||||
invert?: boolean;
|
||||
fullscreen?: boolean;
|
||||
}
|
||||
|
||||
const { meta, invert = false, fullscreen = false } = Astro.props;
|
||||
---
|
||||
|
||||
<html lang="en" class={`${fullscreen ? 'fullscreen' : ''} ${invert ? 'dark text-white' : 'bg-tan text-midnight'}`}>
|
||||
<head>
|
||||
<BaseHead {...meta} />
|
||||
|
||||
<slot name="head" />
|
||||
|
||||
<script>
|
||||
document.body.classList.add('js');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<Sprite.Provider>
|
||||
<SkipLink />
|
||||
<slot name="nav" />
|
||||
|
||||
<slot name="start" />
|
||||
<main id="content" class="container mx-auto px-4 text-base font-base">
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
<slot name="footer" />
|
||||
</Sprite.Provider>
|
||||
|
||||
<script type="module" hoist>
|
||||
import "/src/scripts/defer.ts";
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style>
|
||||
.fullscreen, .fullscreen body {
|
||||
@apply h-full overflow-hidden;
|
||||
}
|
||||
.fullscreen :global(nav) {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
.dark {
|
||||
background-image: var(--gradient-pop-4);
|
||||
}
|
||||
html:not(.fullscreen) main {
|
||||
@apply pt-16 pb-16 sm:pb-24 lg:pb-32;
|
||||
}
|
||||
</style>
|
|
@ -1,69 +1,39 @@
|
|||
---
|
||||
import Page from './Page.astro';
|
||||
import Layout from './Content.astro';
|
||||
import ProseBlock from '../components/blocks/ProseBlock.astro';
|
||||
import TitleBlock from '../components/blocks/TitleBlock.astro';
|
||||
import Date from '../components/Date.astro';
|
||||
import Panel from '../components/Panel.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import Nav from '../components/Nav.astro';
|
||||
import { Markdown } from 'astro/components';
|
||||
|
||||
const { content: { header = '', title = '', description = '', updated_date } = {} } = Astro.props;
|
||||
export interface Props {
|
||||
content: {
|
||||
header?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
updated_date?: string | Date;
|
||||
}
|
||||
}
|
||||
|
||||
const { content } = Astro.props as Props;
|
||||
const { header = '', title = '', description = '', updated_date } = content;
|
||||
---
|
||||
|
||||
<Page {...{ title, description }}>
|
||||
<Panel size="md" background="white linear-gradient(180deg, #E5DAEE 0%, rgba(255, 255, 255, 0) 24rem)">
|
||||
<div id="article">
|
||||
<header>
|
||||
<h1 class="head-md text-gradient">{title}</h1>
|
||||
<p>Last updated on <Date value={updated_date} />.</p>
|
||||
{header && <Markdown content={header} />}
|
||||
</header>
|
||||
|
||||
<hr>
|
||||
<Layout meta={{ title, description }}>
|
||||
<Nav slot="nav" />
|
||||
|
||||
<TitleBlock>
|
||||
<Fragment slot="title">{title}</Fragment>
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
</Panel>
|
||||
</Page>
|
||||
<b class="block pb-2 font-display">Last updated on <Date value={updated_date} />.</b>
|
||||
{header && <Markdown content={header} />}
|
||||
</TitleBlock>
|
||||
|
||||
<ProseBlock>
|
||||
<slot />
|
||||
</ProseBlock>
|
||||
|
||||
<Footer slot="footer" />
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
#article {
|
||||
max-width: 48rem;
|
||||
padding-bottom: 4rem;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
font-family: var(--font-body);
|
||||
font-size: var(--size-500);
|
||||
line-height: 1.3;
|
||||
color: var(--color-midnight);
|
||||
}
|
||||
:where(#article > :global(* + *)) {
|
||||
margin-top: 1em;
|
||||
}
|
||||
#article :global(h3) {
|
||||
margin-top: 2em;
|
||||
margin-bottom: -0.5em;
|
||||
}
|
||||
#article :global(.panel h3) {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
#article :global(h3:nth-child(2)) {
|
||||
margin-top: 0;
|
||||
}
|
||||
header {
|
||||
padding: 3rem 0 2rem;
|
||||
}
|
||||
header h1 {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
header > p {
|
||||
font-family: var(--font-display);
|
||||
}
|
||||
header > p + p {
|
||||
margin-top: 1em;
|
||||
font-family: var(--font-body);
|
||||
}
|
||||
:global(.panel) {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,49 +1,33 @@
|
|||
---
|
||||
import BaseHead from '../components/BaseHead.astro';
|
||||
import BaseLayout from '../components/BaseLayout.astro';
|
||||
import Layout from './Base.astro';
|
||||
import Nav from '../components/Nav.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import type { Props as BaseHeadProps } from '../components/BaseHead.astro';
|
||||
|
||||
import { smartypants } from 'smartypants';
|
||||
|
||||
let { title, description } = Astro.props;
|
||||
title = smartypants(title, 1);
|
||||
const meta = {
|
||||
title: `${title} | Astro`,
|
||||
description,
|
||||
canonicalURL: Astro.request.canonicalURL
|
||||
export interface Props {
|
||||
meta: BaseHeadProps;
|
||||
}
|
||||
|
||||
const { meta } = Astro.props as Props;
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<Layout container meta={meta}>
|
||||
<Nav slot="nav" />
|
||||
|
||||
<head>
|
||||
<BaseHead {...meta} />
|
||||
<slot name="head" />
|
||||
<slot />
|
||||
|
||||
<style>
|
||||
:root {
|
||||
scroll-padding-top: 10rem;
|
||||
background: var(--color-tan);
|
||||
}
|
||||
:global(main) {
|
||||
padding-bottom: 8rem;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<Footer slot="footer" />
|
||||
</Layout>
|
||||
|
||||
<body>
|
||||
<BaseLayout container>
|
||||
<Nav slot="nav" />
|
||||
|
||||
<slot />
|
||||
|
||||
<Footer slot="footer" />
|
||||
</BaseLayout>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<style global>
|
||||
:root {
|
||||
background: var(--color-tan);
|
||||
}
|
||||
main {
|
||||
padding-bottom: 8rem;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
|
@ -1,88 +1,226 @@
|
|||
---
|
||||
import BaseHead from '../components/BaseHead.astro';
|
||||
import BaseLayout from '../components/BaseLayout.astro';
|
||||
import Nav from '../components/Nav.astro';
|
||||
import Wrapper from '../components/Wrapper.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import Layout from './Page.astro';
|
||||
import Card from '../components/blog/Card.astro';
|
||||
import Outro from '../components/blog/Outro.astro';
|
||||
import Panel from '../components/Panel.astro';
|
||||
|
||||
let { content: { title, publishDate, description, authors, socialImage } } = Astro.props;
|
||||
export interface Props {
|
||||
content: {
|
||||
title: string;
|
||||
description: string;
|
||||
authors: string[];
|
||||
publishDate: string | Date;
|
||||
socialImage: string;
|
||||
}
|
||||
}
|
||||
|
||||
const { content: { title, publishDate, description, authors, socialImage } } = Astro.props as Props;
|
||||
const { canonicalURL } = Astro.request;
|
||||
const meta = {
|
||||
title: `${title} | Astro`,
|
||||
title,
|
||||
description,
|
||||
canonicalURL,
|
||||
image: socialImage,
|
||||
}
|
||||
|
||||
console.log(Astro.props);
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<Layout meta={meta}>
|
||||
<Panel size="md" elevation="sm" class="post-header" background="white">
|
||||
<Card post={{ title, description, authors, publishDate }} variant="hero" />
|
||||
</Panel>
|
||||
|
||||
<head>
|
||||
<BaseHead {...meta} />
|
||||
<style>
|
||||
:root {
|
||||
scroll-padding-top: 10rem;
|
||||
background: var(--color-tan);
|
||||
}
|
||||
:global(#content) {
|
||||
min-height: 100vh;
|
||||
padding: 4rem 0;
|
||||
}
|
||||
#article {
|
||||
max-width: 48rem;
|
||||
padding-bottom: 2rem;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
font-family: var(--font-body);
|
||||
font-size: var(--size-500);
|
||||
line-height: 1.3;
|
||||
color: var(--color-midnight);
|
||||
z-index: 1;
|
||||
}
|
||||
:where(#article > :global(* + *)) {
|
||||
margin-top: 1em;
|
||||
}
|
||||
#article :is(h2):not([class]) {
|
||||
margin-top: 3em;
|
||||
}
|
||||
#article > :global(.note:last-child) {
|
||||
margin-top: 8rem;
|
||||
}
|
||||
.hero {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
padding: 3rem 0 2rem;
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<div id="article">
|
||||
<slot />
|
||||
|
||||
<body>
|
||||
<BaseLayout wrapper={Wrapper}>
|
||||
<Nav slot="nav" />
|
||||
|
||||
<Panel size="md" background="white linear-gradient(180deg, #E5DAEE 0%, rgba(255, 255, 255, 0) 24rem)">
|
||||
<div id="article">
|
||||
<header class="hero">
|
||||
<Card post={{ title, description, authors, publishDate }} variant="hero" />
|
||||
</header>
|
||||
|
||||
<hr>
|
||||
<Outro tweet={{ title, href: Astro.request.canonicalURL.toString() }} />
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
<slot />
|
||||
<style global>
|
||||
#content {
|
||||
min-height: 100vh;
|
||||
padding-top: 2rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
.post-header {
|
||||
margin: 1rem auto 3rem;
|
||||
}
|
||||
@media (min-width: 40rem) {
|
||||
.post-header {
|
||||
margin: 4rem auto;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
#article {
|
||||
max-width: 48rem;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
font-family: var(--font-body);
|
||||
font-size: var(--size-500);
|
||||
line-height: 1.3;
|
||||
color: var(--color-midnight);
|
||||
z-index: 1;
|
||||
}
|
||||
:where(#article > * + *) {
|
||||
margin-top: 1em;
|
||||
}
|
||||
#article :is(h1, h2, h3, h4, h5, h6) {
|
||||
font-family: var(--font-display);
|
||||
line-height: 1.1;
|
||||
margin-bottom: 1.25rem;
|
||||
color: var(--color-dusk);
|
||||
}
|
||||
#article hr {
|
||||
border: 0;
|
||||
border-top: 1px solid var(--color-dawn);
|
||||
margin-left: -2rem;
|
||||
margin-right: -2rem;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
#article h1 {
|
||||
--fill: var(--gradient-pop-1);
|
||||
font-size: 3rem;
|
||||
font-size: var(--size-800);
|
||||
}
|
||||
#article h2 {
|
||||
font-size: 2rem;
|
||||
font-size: var(--size-600);
|
||||
margin-top: 2em;
|
||||
margin-bottom: -0.25em;
|
||||
}
|
||||
#article :is(h2):not([class]) {
|
||||
margin-top: 3em;
|
||||
}
|
||||
#article > .note:last-child {
|
||||
margin-top: 8rem;
|
||||
}
|
||||
#article code {
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 400;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
#article code:not([class]) {
|
||||
font-size: 0.85em;
|
||||
color: var(--color-purple);
|
||||
}
|
||||
#article code:not([class])::before {
|
||||
content: "`";
|
||||
}
|
||||
#article code:not([class])::after {
|
||||
content: "`";
|
||||
}
|
||||
#article img {
|
||||
max-width: 100%;
|
||||
}
|
||||
#article :is(h2, h3, h4, h5, h6) a {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
text-decoration: none !important;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
<Outro tweet={{ title, href: canonicalURL.toString() }} />
|
||||
</div>
|
||||
</Panel>
|
||||
#article :is(h2, h3, h4, h5, h6) a::before {
|
||||
content: "#";
|
||||
width: 1em;
|
||||
margin-left: 0.25em;
|
||||
color: inherit;
|
||||
opacity: 0;
|
||||
transition: opacity 200ms cubic-bezier(0.23, 1, 0.32, 1);
|
||||
order: 999;
|
||||
}
|
||||
|
||||
#article :is(h2, h3, h4, h5, h6) a:is(:active, :visited, :hover, :focus) {
|
||||
color: var(--color-dusk);
|
||||
}
|
||||
|
||||
<Footer slot="footer" />
|
||||
</BaseLayout>
|
||||
</body>
|
||||
#article :is(h2, h3, h4, h5, h6) a:active::before,
|
||||
#article :is(h2, h3, h4, h5, h6) a:hover::before,
|
||||
#article :is(h2, h3, h4, h5, h6) a:focus::before {
|
||||
opacity: 0.6 !important;
|
||||
}
|
||||
|
||||
</html>
|
||||
#article :is(strong, b) {
|
||||
font-family: inherit;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#article :is(em, i) {
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
#article :is(ul:not([role="list"]), ol:not([role="list"])) {
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
|
||||
#article :where(ul:not([role="list"])) {
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
#article :where(ul:not([role="list"]) > li + li) {
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
|
||||
#article ::marker {
|
||||
color: rgba(var(--color-midnight-rgb), 0.5);
|
||||
}
|
||||
|
||||
#article pre > code:not([class*="language"]) {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#article pre > code {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
#article pre {
|
||||
position: relative;
|
||||
--padding-block: 1rem;
|
||||
--padding-inline: 2rem;
|
||||
padding: var(--padding-block) var(--padding-inline);
|
||||
padding-right: calc(var(--padding-inline) * 2);
|
||||
margin-left: calc(var(--padding-inline) * -1);
|
||||
margin-right: calc(var(--padding-inline) * -1);
|
||||
font-family: var(--font-mono);
|
||||
|
||||
line-height: 1.5;
|
||||
font-size: 0.85em;
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
#article pre {
|
||||
background: linear-gradient(to bottom, var(--color-midnight), #1f1638);
|
||||
color: white;
|
||||
}
|
||||
|
||||
#article table {
|
||||
width: 100%;
|
||||
padding: var(--padding-block) 0;
|
||||
margin: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
/* Zebra striping */
|
||||
#article tr:nth-of-type(odd) {
|
||||
background: var(--theme-bg-hover);
|
||||
}
|
||||
#article th {
|
||||
background: var(--color-black);
|
||||
color: var(--theme-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
#article td,
|
||||
#article th {
|
||||
padding: 6px;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,97 +1,28 @@
|
|||
---
|
||||
import BaseHead from '../components/BaseHead.astro';
|
||||
import BaseLayout from '../components/BaseLayout.astro';
|
||||
import Nav from '../components/Nav.astro';
|
||||
import PixelLink from '../components/PixelLink.astro';
|
||||
import Starfield from '../components/Starfield.astro';
|
||||
import Layout from '../layouts/Content.astro';
|
||||
|
||||
const meta = {
|
||||
title: 'Page Not Found | Astro',
|
||||
title: 'Page Not Found',
|
||||
description: 'Astro is a new kind of static site builder for the modern web. Powerful developer experience meets lightweight output.',
|
||||
canonicalURL: new URL('./404', Astro.site)
|
||||
}
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<Layout fullscreen invert meta={meta}>
|
||||
<Fragment slot="head">
|
||||
<base href="/404" />
|
||||
</Fragment>
|
||||
|
||||
<head>
|
||||
<BaseHead {...meta} />
|
||||
<style>
|
||||
:root {
|
||||
scroll-padding-top: 10rem;
|
||||
}
|
||||
:global(main) {
|
||||
min-height: calc(100vh - 32px);
|
||||
max-width: 100vw;
|
||||
overflow: hidden;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
background-image: var(--gradient-pop-4);
|
||||
}
|
||||
:global(nav) {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
.text {
|
||||
z-index: 1;
|
||||
padding: 1rem;
|
||||
margin-top: -4rem;
|
||||
}
|
||||
h2 {
|
||||
--fill: white;
|
||||
font-size: 4rem;
|
||||
font-size: var(--size-900);
|
||||
font-family: var(--font-display);
|
||||
line-height: 1.1;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
p {
|
||||
font-size: var(--size-500);
|
||||
max-width: min(64ch, calc(100% - 1rem));
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
.cta {
|
||||
position: relative;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1;
|
||||
}
|
||||
<Nav invert slot="nav" />
|
||||
|
||||
@media (min-width: 52rem) {
|
||||
.cta {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
.cta > :global(*) {
|
||||
box-sizing: border-box;
|
||||
margin: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
<base href="/404" />
|
||||
</head>
|
||||
<Starfield height={64} />
|
||||
|
||||
<body>
|
||||
<BaseLayout>
|
||||
<Nav invert marginBottom slot="nav" />
|
||||
|
||||
<Starfield height={64} />
|
||||
|
||||
<div class="container text">
|
||||
<h2 class="text-gradient">Lost in space there, astronaut?</h2>
|
||||
<p>We couldn’t find the page you were looking for—let’s get you back to HQ.</p>
|
||||
<div class="cta container">
|
||||
<PixelLink href="/">Return Home</PixelLink>
|
||||
</div>
|
||||
</div>
|
||||
</BaseLayout>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<div class="h-full flex flex-col justify-center items-center text-center pt-[25vh]">
|
||||
<h2 class="font-display text-3xl font-bold pb-6">Lost in space there, astronaut?</h2>
|
||||
<p class="pb-8">We couldn’t find the page you were looking for—let’s get you back to HQ.</p>
|
||||
<PixelLink href="/">Return Home</PixelLink>
|
||||
</div>
|
||||
</Layout>
|
||||
|
|
|
@ -1,118 +1,50 @@
|
|||
---
|
||||
import Page from '../layouts/Page.astro';
|
||||
import Nav from '../components/Nav.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import Layout from '../layouts/Content.astro';
|
||||
import ContributorsAvatarList from '../components/ContributorsAvatarList.astro';
|
||||
import PixelLink from '../components/PixelLink.astro';
|
||||
|
||||
const meta = { title: 'About' };
|
||||
---
|
||||
|
||||
<Page title="About">
|
||||
<header>
|
||||
<h1 class="title text-gradient">What is Astro?</h1>
|
||||
</header>
|
||||
<Layout meta={meta}>
|
||||
<Nav slot="nav" />
|
||||
|
||||
<section>
|
||||
<p><strong>Astro</strong> helps web developers build better websites in less time. Astro is an MIT-licensed, open source build tool that combines a modern developer experience with efficient, lightweight output. The end result? Beautiful websites that work great on any device, across any internet connection.</p>
|
||||
<div class="prose mx-auto">
|
||||
<header>
|
||||
<h1 class="text-3xl text-gradient">What is Astro?</h1>
|
||||
</header>
|
||||
|
||||
<p>Astro launched 2021 and revolutionized web performance by integrating <strong>partial hydration</strong> -- a previously difficult-to-setup technology -- directly into the Astro runtime with built-in support for popular frameworks React, Svelte, Vue, and Solid.js.</p>
|
||||
<section>
|
||||
<p><strong>Astro</strong> helps web developers build better websites in less time. Astro is an MIT-licensed, open source build tool that combines a modern developer experience with efficient, lightweight output. The end result? Beautiful websites that work great on any device, across any internet connection.</p>
|
||||
|
||||
<p>In less than a year, Astro amassed a huge community of contributors and an even larger audience of 10,000+ users at companies like Google, Netlify, Trivago and more. Astro won the <a href="https://jamstackconf.com/jammies/">"Ecosystem Innovation Award"</a> at last year's JamstackConf.</p>
|
||||
<p>Astro launched 2021 and revolutionized web performance by integrating <strong>partial hydration</strong> -- a previously difficult-to-setup technology -- directly into the Astro runtime with built-in support for popular frameworks React, Svelte, Vue, and Solid.js.</p>
|
||||
|
||||
<!-- <p>TODO Block - Bulleted highlights on the team.</p> -->
|
||||
<!-- <p>TODO Block - Call to action.</p> -->
|
||||
<p>In less than a year, Astro amassed a huge community of contributors and an even larger audience of 10,000+ users at companies like Google, Netlify, Trivago and more. Astro won the <a href="https://jamstackconf.com/jammies/">"Ecosystem Innovation Award"</a> at last year's JamstackConf.</p>
|
||||
|
||||
</section>
|
||||
<section style="margin: 2rem 0;">
|
||||
<h2 class="title text-gradient">Our Community</h2>
|
||||
<p><strong>Astro</strong> is an open source project powered by hundreds of contributors making thousands of individual contributions. You can see many of us on this page!</p>
|
||||
<!-- <p>TODO Block - Bulleted highlights on the team.</p> -->
|
||||
<!-- <p>TODO Block - Call to action.</p> -->
|
||||
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="text-center text-gradient">Our Community</h2>
|
||||
<p><strong>Astro</strong> is an open source project powered by hundreds of contributors making thousands of individual contributions. You can see many of us on this page!</p>
|
||||
|
||||
<p>Open source means that all of our work is done in public, and anyone can get involved and contribute. Visit us <a href="https://astro.build/chat">on Discord</a> and come say "hi 👋" to learn more.</p>
|
||||
|
||||
<p>Want to get paid to work on Astro? Check out open roles at <a href="/company">The Astro Technology Company</a>.</p>
|
||||
<ContributorsAvatarList />
|
||||
</section>
|
||||
<!-- TODO: instructions on how to get involved - either full time (link to company) or through open source
|
||||
|
||||
<p>Open source means that all of our work is done in public, and anyone can get involved and contribute. Visit us <a href="https://astro.build/chat">on Discord</a> and come say "hi 👋" to learn more.</p>
|
||||
|
||||
<section style="margin: 2rem 0;">
|
||||
<h2 id="get-involved" class="title text-gradient">Get involved</h2>
|
||||
<p>instructions on how to get involved - either full time (link to company) or through open source</p>
|
||||
</section>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<p>Want to get paid to work on Astro? Check out open roles at <a href="/company">The Astro Technology Company</a>.</p>
|
||||
<ContributorsAvatarList />
|
||||
</section>
|
||||
<!-- TODO: instructions on how to get involved - either full time (link to company) or through open source
|
||||
|
||||
|
||||
<section style="margin: 2rem 0;">
|
||||
<h2 id="get-involved" class="title text-gradient">Get involved</h2>
|
||||
<p>instructions on how to get involved - either full time (link to company) or through open source</p>
|
||||
</section>
|
||||
-->
|
||||
</Page>
|
||||
<Footer slot="footer" />
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
header {
|
||||
padding: 3rem 2rem 2rem;
|
||||
width: 100%;
|
||||
max-width: 64rem;
|
||||
}
|
||||
section {
|
||||
padding: 0 2rem;
|
||||
width: 100%;
|
||||
max-width: 64rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
section p {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
h1.title {
|
||||
font-family: var(--font-display);
|
||||
--fill: var(--gradient-pop-1);
|
||||
font-size: var(--size-900);
|
||||
}
|
||||
h2.title {
|
||||
font-family: var(--font-display);
|
||||
--fill: var(--gradient-pop-1);
|
||||
font-size: var(--size-800);
|
||||
text-align: center;
|
||||
margin: 1.5rem;
|
||||
}
|
||||
.posts {
|
||||
width: 100%;
|
||||
max-width: 64rem;
|
||||
padding: 2rem;
|
||||
padding-bottom: 4rem;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
font-family: var(--font-body);
|
||||
font-size: var(--size-500);
|
||||
line-height: 1.3;
|
||||
color: var(--color-midnight);
|
||||
}
|
||||
.post + .post {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.post {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
padding: 2rem;
|
||||
margin-left: -2rem;
|
||||
margin-right: -2rem;
|
||||
background: var(--color-tan);
|
||||
box-shadow: var(--shadow-sm);
|
||||
border-radius: var(--corner-md);
|
||||
font-family: var(--font-body);
|
||||
font-size: var(--size-500);
|
||||
line-height: 1.3;
|
||||
color: var(--color-midnight);
|
||||
}
|
||||
.post:hover,
|
||||
.post:focus-within {
|
||||
background: linear-gradient(to top, var(--color-dawn), white);
|
||||
}
|
||||
:is(.post:hover, .post:focus-within) .title {
|
||||
--fill: var(--gradient-pop-1);
|
||||
}
|
||||
.post :global(a) {
|
||||
z-index: 1;
|
||||
}
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
z-index: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
---
|
||||
import Page from '../../layouts/Page.astro';
|
||||
import Layout from '../../layouts/Page.astro';
|
||||
import Card from '../../components/blog/Card.astro';
|
||||
import { getAllPosts } from '../../posts';
|
||||
|
||||
const posts = await getAllPosts();
|
||||
|
||||
const meta = { title: 'Blog' };
|
||||
---
|
||||
|
||||
<Page title="Blog">
|
||||
<Layout meta={meta}>
|
||||
<header>
|
||||
<h1 class="title text-gradient">Blog</h1>
|
||||
<p></p>
|
||||
|
@ -22,7 +24,7 @@ const posts = await getAllPosts();
|
|||
)
|
||||
})}
|
||||
</ul>
|
||||
</Page>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
header {
|
||||
|
@ -59,7 +61,7 @@ const posts = await getAllPosts();
|
|||
margin-left: -2rem;
|
||||
margin-right: -2rem;
|
||||
background: white;
|
||||
box-shadow: var(--shadow-md);
|
||||
box-shadow: var(--shadow-sm);
|
||||
border-radius: var(--corner-md);
|
||||
font-family: var(--font-body);
|
||||
font-size: var(--size-500);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import Page from '../layouts/Page.astro';
|
||||
import Layout from '../layouts/Page.astro';
|
||||
import Card from '../components/careers/Card.astro';
|
||||
|
||||
const posts = [{
|
||||
|
@ -15,9 +15,14 @@ const posts = [{
|
|||
title: 'Product Designer',
|
||||
description: 'Full Time • Remote • United States, Canada'
|
||||
}]
|
||||
|
||||
const meta = {
|
||||
title: 'The Astro Technology Company',
|
||||
description: "We're hiring! The Astro Technology Company was formed to support the long-term success of the Astro project and grow Astro into the best possible platform for web development. Learn more."
|
||||
}
|
||||
---
|
||||
|
||||
<Page title="The Astro Technology Company" description="We're hiring! The Astro Technology Company was formed to support the long-term success of the Astro project and grow Astro into the best possible platform for web development. Learn more.">
|
||||
<Layout meta={meta}>
|
||||
<header>
|
||||
<h1 class="title text-gradient">The Astro Technology Company</h1>
|
||||
</header>
|
||||
|
@ -43,7 +48,7 @@ const posts = [{
|
|||
})}
|
||||
</ul>
|
||||
</section>
|
||||
</Page>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
header {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
---
|
||||
import { Icon, Sprite } from 'astro-icon';
|
||||
import Banner from '../components/Banner.astro';
|
||||
import BaseHead from '../components/BaseHead.astro';
|
||||
import BaseLayout from '../components/BaseLayout.astro';
|
||||
import Nav from '../components/Nav.astro';
|
||||
import PixelLink from '../components/PixelLink.astro';
|
||||
import Panel from '../components/Panel.astro';
|
||||
|
@ -10,6 +8,8 @@ import Checklist from '../components/Checklist.astro';
|
|||
import ChecklistItem from '../components/ChecklistItem.astro';
|
||||
import ArrowLink from '../components/ArrowLink.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import Noscript from '../components/Noscript.astro';
|
||||
import Layout from '../layouts/Base.astro';
|
||||
|
||||
import Title from '../components/landing/Title.astro';
|
||||
import Hero from '../components/landing/Hero.astro';
|
||||
|
@ -27,157 +27,143 @@ const headline = 'Build fast websites, faster.'
|
|||
const tagline = 'Astro is a new kind of static site builder for the modern web. Powerful developer experience meets lightweight output.'
|
||||
|
||||
const meta = {
|
||||
title: 'Astro',
|
||||
description: `${headline} ${tagline}`,
|
||||
canonicalURL: new URL('.', Astro.site)
|
||||
}
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<Layout meta={meta}>
|
||||
<Fragment slot="banner">
|
||||
<Noscript />
|
||||
<Banner href="/blog/the-astro-technology-company/" items={[`Announcing the Astro Technology Company!`, `Investing in the future of Astro.`]} />
|
||||
</Fragment>
|
||||
|
||||
<head>
|
||||
<BaseHead {...meta} />
|
||||
<style global>
|
||||
:root {
|
||||
scroll-padding-top: 10rem;
|
||||
}
|
||||
main {
|
||||
max-width: 100vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<Nav marginBottom slot="nav" />
|
||||
|
||||
<body>
|
||||
<Banner href="/blog/the-astro-technology-company/" items={[`Announcing the Astro Technology Company!`, `Investing in the future of Astro.`]} />
|
||||
<BaseLayout>
|
||||
<Nav marginBottom slot="nav" />
|
||||
<Hero>
|
||||
<Fragment slot="title">{headline}</Fragment>
|
||||
<Fragment slot="tagline">{tagline}</Fragment>
|
||||
<PixelLink href="https://docs.astro.build">Read the docs</PixelLink>
|
||||
<ArrowLink always href="https://astro.new">Get Started</ArrowLink>
|
||||
</Hero>
|
||||
|
||||
<Trusted>
|
||||
<Fragment slot="title">Developers around the world rely on Astro</Fragment>
|
||||
<Fragment>
|
||||
<li>
|
||||
<Icon name="logos/google" title="Google" height="36" />
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos/netlify" title="Netlify" height="36" />
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos/trivago" title="Trivago" height="40" />
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos/divriots" title="Div Riots" height="28" />
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos/monogram" title="monogram" height="40" width="240" />
|
||||
</li>
|
||||
</Fragment>
|
||||
</Trusted>
|
||||
|
||||
<Hero>
|
||||
<Fragment slot="title">{headline}</Fragment>
|
||||
<Fragment slot="tagline">{tagline}</Fragment>
|
||||
<PixelLink href="https://docs.astro.build">Read the docs</PixelLink>
|
||||
<ArrowLink always href="https://astro.new">Get Started</ArrowLink>
|
||||
</Hero>
|
||||
|
||||
<Trusted>
|
||||
<Fragment slot="title">Developers around the world rely on Astro</Fragment>
|
||||
<Fragment>
|
||||
<li>
|
||||
<Icon name="logos/google" title="Google" height="36" />
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos/netlify" title="Netlify" height="36" />
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos/trivago" title="Trivago" height="40" />
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos/divriots" title="Div Riots" height="28" />
|
||||
</li>
|
||||
<li>
|
||||
<Icon name="logos/monogram" title="monogram" height="40" width="240" />
|
||||
</li>
|
||||
<Demo gradient>
|
||||
<Title slot="title" id="more-html-less-javascript">More HTML, Less JavaScript</Title>
|
||||
<p>Astro uses a modern server-side templating language that renders directly to HTML & CSS, eliminating heavy JavaScript automatically.</p>
|
||||
<DemoTTI slot="illustration" />
|
||||
</Demo>
|
||||
|
||||
<Demo reverse>
|
||||
<Title slot="title" id="automatic-partial-hydration">Automatic Partial Hydration</Title>
|
||||
<p>Meet Astro’s magic tool for web optimization. Astro is the first site builder to eliminate dead code from your website and only hydrate your essential, interactive UI.</p>
|
||||
<ArrowLink always href="https://docs.astro.build/en/core-concepts/component-hydration/">Learn more about Partial Hydration</ArrowLink>
|
||||
<DemoPartialHydration slot="illustration" />
|
||||
</Demo>
|
||||
|
||||
<Section>
|
||||
<Panel pad={2} background="var(--gradient-pop-3)">
|
||||
<Fragment slot="title">
|
||||
<h3 class="head-md"><Title id="byof">Bring your favorite framework</Title></h3>
|
||||
<p style="margin-top: 0.5rem;">Astro natively supports every popular framework—you can even mix and match!</p>
|
||||
</Fragment>
|
||||
</Trusted>
|
||||
|
||||
<Demo gradient>
|
||||
<Title slot="title" id="more-html-less-javascript">More HTML, Less JavaScript</Title>
|
||||
<p>Astro uses a modern server-side templating language that renders directly to HTML & CSS, eliminating heavy JavaScript automatically.</p>
|
||||
<DemoTTI slot="illustration" />
|
||||
</Demo>
|
||||
<Checklist cols={4}>
|
||||
<ChecklistItem href="https://astro.new/framework-react">
|
||||
<Sprite role="img" name="frameworks/react" size={24} slot="icon" />
|
||||
React
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-svelte">
|
||||
<Sprite role="img" name="frameworks/svelte" size={24} slot="icon" />
|
||||
Svelte
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-vue">
|
||||
<Sprite role="img" name="frameworks/vue" size={24} slot="icon" />
|
||||
Vue
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-solid">
|
||||
<Sprite role="img" name="frameworks/solid" size={24} slot="icon" />
|
||||
Solid
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-preact">
|
||||
<Sprite role="img" name="frameworks/preact" size={24} slot="icon" />
|
||||
Preact
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-alpine">
|
||||
<Sprite role="img" name="frameworks/alpine" size={24} slot="icon" />
|
||||
Alpine
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-lit">
|
||||
<Sprite role="img" name="frameworks/lit" size={24} slot="icon" />
|
||||
Lit
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/minimal">
|
||||
<Sprite role="img" name="frameworks/js" size={24} slot="icon" />
|
||||
Vanilla
|
||||
</ChecklistItem>
|
||||
</Checklist>
|
||||
</Panel>
|
||||
</Section>
|
||||
|
||||
<Demo reverse>
|
||||
<Title slot="title" id="automatic-partial-hydration">Automatic Partial Hydration</Title>
|
||||
<p>Meet Astro’s magic tool for web optimization. Astro is the first site builder to eliminate dead code from your website and only hydrate your essential, interactive UI.</p>
|
||||
<ArrowLink always href="https://docs.astro.build/en/core-concepts/component-hydration/">Learn more about Partial Hydration</ArrowLink>
|
||||
<DemoPartialHydration slot="illustration" />
|
||||
</Demo>
|
||||
<Integrations>
|
||||
<Title slot="title" id="build-extend-deploy">
|
||||
Build, Extend, Deploy
|
||||
</Title>
|
||||
<Fragment>
|
||||
<p>Whatever you’re building, Astro has you covered. With convenient, out-of-the-box features and even more ready-to-use integrations, Astro has everything that you need to build.</p>
|
||||
</Fragment>
|
||||
</Integrations>
|
||||
|
||||
<Section>
|
||||
<Panel pad={2} background="var(--gradient-pop-3)">
|
||||
<Fragment slot="title">
|
||||
<h3 class="head-md"><Title id="byof">Bring your favorite framework</Title></h3>
|
||||
<p style="margin-top: 0.5rem;">Astro natively supports every popular framework—you can even mix and match!</p>
|
||||
</Fragment>
|
||||
<Performance>
|
||||
<Title slot="title" id="peak-performance">Peak Performance</Title>
|
||||
<Fragment>
|
||||
<p>Site performance has a tangible impact on the success of your business. Astro sites can be up to 40% faster and use 90% less JavaScript compared to leading static site generators.</p>
|
||||
<p style="opacity: 0.75; margin-top: 1rem;">
|
||||
<small>87% of websites currently fail Google's Core Web Vitals (CWV) benchmark. Astro is on a mission to change that.</small>
|
||||
</p>
|
||||
</Fragment>
|
||||
</Performance>
|
||||
|
||||
<Checklist cols={4}>
|
||||
<ChecklistItem href="https://astro.new/framework-react">
|
||||
<Sprite role="img" name="frameworks/react" size={24} slot="icon" />
|
||||
React
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-svelte">
|
||||
<Sprite role="img" name="frameworks/svelte" size={24} slot="icon" />
|
||||
Svelte
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-vue">
|
||||
<Sprite role="img" name="frameworks/vue" size={24} slot="icon" />
|
||||
Vue
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-solid">
|
||||
<Sprite role="img" name="frameworks/solid" size={24} slot="icon" />
|
||||
Solid
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-preact">
|
||||
<Sprite role="img" name="frameworks/preact" size={24} slot="icon" />
|
||||
Preact
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-alpine">
|
||||
<Sprite role="img" name="frameworks/alpine" size={24} slot="icon" />
|
||||
Alpine
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/framework-lit">
|
||||
<Sprite role="img" name="frameworks/lit" size={24} slot="icon" />
|
||||
Lit
|
||||
</ChecklistItem>
|
||||
<ChecklistItem href="https://astro.new/minimal">
|
||||
<Sprite role="img" name="frameworks/js" size={24} slot="icon" />
|
||||
Vanilla
|
||||
</ChecklistItem>
|
||||
</Checklist>
|
||||
</Panel>
|
||||
</Section>
|
||||
<Quote pad={1.5}>
|
||||
<a slot="logo" href="https://devtools.fm/episode/14">
|
||||
<span>
|
||||
<Sprite width="9em" height="3em" name="logos/devtoolsfm" title="devtools.fm" />
|
||||
</span>
|
||||
</a>
|
||||
<Fragment slot="quote">Astro is really shaping up to be one of the formative ways to build mostly-static sites.</Fragment>
|
||||
<Fragment slot="cite">Justin Bennett, devtools.fm Host</Fragment>
|
||||
</Quote>
|
||||
|
||||
<Integrations>
|
||||
<Title slot="title" id="build-extend-deploy">
|
||||
Build, Extend, Deploy
|
||||
</Title>
|
||||
<Fragment>
|
||||
<p>Whatever you’re building, Astro has you covered. With convenient, out-of-the-box features and even more ready-to-use integrations, Astro has everything that you need to build.</p>
|
||||
</Fragment>
|
||||
</Integrations>
|
||||
<Sponsors>
|
||||
<Title id="sponsors" slot="title">Sponsored by</Title>
|
||||
<ArrowLink always href="https://opencollective.com/astrodotbuild" slot="cta">Become a sponsor</ArrowLink>
|
||||
</Sponsors>
|
||||
|
||||
<Performance>
|
||||
<Title slot="title" id="peak-performance">Peak Performance</Title>
|
||||
<Fragment>
|
||||
<p>Site performance has a tangible impact on the success of your business. Astro sites can be up to 40% faster and use 90% less JavaScript compared to leading static site generators.</p>
|
||||
<p style="opacity: 0.75; margin-top: 1rem;">
|
||||
<small>87% of websites currently fail Google's Core Web Vitals (CWV) benchmark. Astro is on a mission to change that.</small>
|
||||
</p>
|
||||
</Fragment>
|
||||
</Performance>
|
||||
<Footer slot="footer" />
|
||||
|
||||
<Quote pad={1.5}>
|
||||
<a slot="logo" href="https://devtools.fm/episode/14">
|
||||
<span>
|
||||
<Sprite width="9em" height="3em" name="logos/devtoolsfm" title="devtools.fm" />
|
||||
</span>
|
||||
</a>
|
||||
<Fragment slot="quote">Astro is really shaping up to be one of the formative ways to build mostly-static sites.</Fragment>
|
||||
<Fragment slot="cite">Justin Bennett, devtools.fm Host</Fragment>
|
||||
</Quote>
|
||||
|
||||
<Sponsors>
|
||||
<Title id="sponsors" slot="title">Sponsored by</Title>
|
||||
<ArrowLink always href="https://opencollective.com/astrodotbuild" slot="cta">Become a sponsor</ArrowLink>
|
||||
</Sponsors>
|
||||
|
||||
<Footer slot="footer" />
|
||||
</BaseLayout>
|
||||
<Noscript />
|
||||
|
||||
<script type="module" hoist>
|
||||
import "/src/scripts/animations.ts";
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</Layout>
|
||||
|
|
99
smoke/astro.build-main/src/pages/press.astro
Normal file
|
@ -0,0 +1,99 @@
|
|||
---
|
||||
import { smartypants } from 'smartypants';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import Nav from '../components/Nav.astro';
|
||||
import Layout from '../layouts/Content.astro';
|
||||
|
||||
const meta = {
|
||||
title: 'Press',
|
||||
}
|
||||
|
||||
const assets = [
|
||||
{
|
||||
title: 'Full Logo Light',
|
||||
description: 'Please use this logo in most circumstances on light backgrounds.',
|
||||
background: 'light',
|
||||
svg: '/assets/press/full-logo-light.svg',
|
||||
png: '/assets/press/full-logo-light.png'
|
||||
},
|
||||
{
|
||||
title: 'Full Logo Dark',
|
||||
description: 'Please use this logo in most circumstances on dark backgrounds.',
|
||||
background: 'dark',
|
||||
svg: '/assets/press/full-logo-dark.svg',
|
||||
png: '/assets/press/full-logo-dark.png'
|
||||
},
|
||||
{
|
||||
title: 'Simple Full Logo Light',
|
||||
description: "Please use this logo in cases where the Full Logo Light won't work.",
|
||||
background: 'light',
|
||||
svg: '/assets/press/simple-full-logo-light.svg',
|
||||
png: '/assets/press/simple-full-logo-light.png'
|
||||
},
|
||||
{
|
||||
title: 'Simple Full Logo Dark',
|
||||
description: "Please use this logo in cases where the Full Logo Dark won't work.",
|
||||
background: 'dark',
|
||||
svg: '/assets/press/simple-full-logo-dark.svg',
|
||||
png: '/assets/press/simple-full-logo-dark.png'
|
||||
},
|
||||
{
|
||||
title: 'Logomark Light',
|
||||
description: 'Please only use the logomark for very small representations of Astro and in illustrations with written consent by Astro.',
|
||||
background: 'light',
|
||||
svg: '/assets/press/logomark-light.svg',
|
||||
png: '/assets/press/logomark-light.png'
|
||||
},
|
||||
{
|
||||
title: 'Logomark Dark',
|
||||
description: 'Please only use the logomark for very small representations of Astro and in illustrations with written consent by Astro.',
|
||||
background: 'dark',
|
||||
svg: '/assets/press/logomark-dark.svg',
|
||||
png: '/assets/press/logomark-dark.png'
|
||||
},
|
||||
{
|
||||
title: 'Simple Logomark Light',
|
||||
description: "Please only use this logomark if the full-color logomark won't work and be sure to abide by the same rules as outlined in the full-color logomark's brief description.",
|
||||
background: 'light',
|
||||
svg: '/assets/press/simple-logomark-light.svg',
|
||||
png: '/assets/press/simple-logomark-light.png'
|
||||
},
|
||||
{
|
||||
title: 'Simple Logomark Dark',
|
||||
description: 'Please only use this logomark in cases where there is a busy dark/colored/photo background and abide by the same rules as the full-color logomark.',
|
||||
background: 'dark',
|
||||
svg: '/assets/press/simple-logomark-dark.svg',
|
||||
png: '/assets/press/simple-logomark-dark.png'
|
||||
}
|
||||
]
|
||||
---
|
||||
|
||||
<Layout meta={meta}>
|
||||
<Nav slot="nav" />
|
||||
|
||||
<header class="text-center max-w-4xl mx-auto pb-24 lg:pb-32">
|
||||
<h1 class="font-display text-3xl font-bold mb-6 text-gradient">Astro Logos</h1>
|
||||
<p>Feel free to download and use the logo assets below. Please do not modify or change the resources below. Be sure to abide by the usage rules noted under each asset.</p>
|
||||
</header>
|
||||
|
||||
<div class="grid gap-x-4 gap-y-16 sm:grid-cols-2 md:grid-col-3 lg:grid-cols-4">
|
||||
{assets.map(asset => (
|
||||
<article class="flex flex-col">
|
||||
<div class={`aspect-w-16 aspect-h-9 ${asset.background === 'light' ? 'bg-white' : 'bg-black'}`}>
|
||||
<div class="flex items-center justify-center">
|
||||
<img class="w-3/4 h-auto max-h-16" src={asset.svg} />
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="text-md font-bold mt-4 mb-6">{asset.title}</h2>
|
||||
<p class="text-sm flex-1" set:html={smartypants(asset.description)}></p>
|
||||
|
||||
<footer class="pt-6">
|
||||
<a class="text-sm font-semibold px-4 py-2 bg-dusk text-white rounded inline-block" href={asset.svg}>SVG</a>
|
||||
<a class="text-sm font-semibold px-4 py-2 bg-dusk text-white rounded inline-block" href={asset.png}>PNG</a>
|
||||
</footer>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Footer slot="footer" />
|
||||
</Layout>
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
setup: |
|
||||
import Layout from '../layouts/Legal.astro'
|
||||
import Panel from '../components/Panel.astro'
|
||||
import PanelBlock from '../components/blocks/PanelBlock.astro'
|
||||
title: Privacy Policy
|
||||
updated_date: Jan 6, 2022
|
||||
description: Astro's privacy policy
|
||||
|
@ -53,15 +53,15 @@ As a user you may also request a copy of your data and that your data be updated
|
|||
|
||||
### We may share your information with
|
||||
|
||||
<Panel background="var(--color-dawn)">
|
||||
<PanelBlock>
|
||||
|
||||
### Google Analytics (Google, Inc.)
|
||||
#### Google Analytics (Google, Inc.)
|
||||
|
||||
Google Inc. utilizes the Data collected to track and examine the use of this Application, to prepare reports on its activities and share them with other Google services.
|
||||
|
||||
US – [Privacy Policy](https://www.google.com/intl/en/policies/privacy/)
|
||||
|
||||
</Panel>
|
||||
</PanelBlock>
|
||||
|
||||
### EU/EEA - US Data Transfers
|
||||
|
||||
|
|
114
smoke/astro.build-main/src/pages/thank-you.astro
Normal file
|
@ -0,0 +1,114 @@
|
|||
---
|
||||
import Nav from '../components/Nav.astro';
|
||||
import Starfield from '../components/Starfield.astro';
|
||||
import Layout from '../layouts/Content.astro';
|
||||
import contributors from '../data/contributors.json';
|
||||
|
||||
const {staff, l3, l2, l1} = contributors;
|
||||
const contributorLists = [
|
||||
{
|
||||
title: 'Staff',
|
||||
members: staff,
|
||||
},
|
||||
{
|
||||
title: 'Core',
|
||||
members: l3,
|
||||
},
|
||||
{
|
||||
title: 'Maintainer',
|
||||
members: l2,
|
||||
},
|
||||
{
|
||||
title: 'Contributor',
|
||||
members: l1,
|
||||
}
|
||||
];
|
||||
|
||||
const contributorsCount = staff.length + l3.length + l2.length + l1.length
|
||||
|
||||
const meta = { title: 'Thank you' };
|
||||
|
||||
function centerOnDesktop(list, i) {
|
||||
return (list.length - 1 === i) && (i % 3 === 0)
|
||||
}
|
||||
---
|
||||
|
||||
<Layout fullscreen invert meta={meta}>
|
||||
<Nav invert slot="nav" />
|
||||
|
||||
<Starfield height={64} />
|
||||
|
||||
<div class="font-display mt-10 overflow-hidden">
|
||||
<div class="credits max-w-3xl mx-auto flex flex-col items-center text-center pt-[20vh]">
|
||||
<h1 class="text-3xl font-bold pb-12">Thank you</h1>
|
||||
<p class="font-thin"><b>Astro</b> is an open source project powered by hundreds of contributors making thousands of individual contributions.</p>
|
||||
|
||||
<section id="contributors" class="grid sm:grid-cols-2 lg:grid-cols-3 gap-y-1 gap-x-12">
|
||||
{contributorLists.map(({ title, members }) => (
|
||||
<Fragment>
|
||||
<h2 class="pt-16 pb-6 text-xl font-bold col-span-full">{title}</h2>
|
||||
{members.map((member, i) => (
|
||||
<p class={centerOnDesktop(members, i) ? "lg:col-start-2": ""}>{member.login}</p>
|
||||
))}
|
||||
</Fragment>
|
||||
))}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
<script type="module">
|
||||
const credits = document.querySelector('.credits');
|
||||
|
||||
function onAnimationEnd(event) {
|
||||
if (event.animationName === 'credits') {
|
||||
credits.classList.add('done');
|
||||
credits.removeEventListener('animationend', onAnimationEnd);
|
||||
}
|
||||
}
|
||||
|
||||
credits.addEventListener('animationend', onAnimationEnd);
|
||||
</script>
|
||||
|
||||
<style define:vars={{contributorsCount}}>
|
||||
.credits {
|
||||
animation-duration: calc(1s * var(--contributorsCount));
|
||||
animation-name: credits;
|
||||
animation-delay: 2s;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
@screen sm {
|
||||
.credits {
|
||||
animation-duration: calc(0.75s * var(--contributorsCount));
|
||||
}
|
||||
}
|
||||
|
||||
@screen lg {
|
||||
.credits {
|
||||
animation-duration: calc(0.5s * var(--contributorsCount));
|
||||
}
|
||||
}
|
||||
|
||||
#contributors {
|
||||
opacity: 0;
|
||||
animation-duration: 2s;
|
||||
animation-delay: 2s;
|
||||
animation-name: fade;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
.credits.done #contributors {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@keyframes credits {
|
||||
from { transform: translate3d(0, 0, 0); }
|
||||
to { transform: translate3d(0, -100%, 0); }
|
||||
}
|
||||
|
||||
@keyframes fade {
|
||||
0% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
</style>
|
|
@ -13,9 +13,10 @@ authors:
|
|||
- [Dynamic File Routes](#dynamic-file-routes)
|
||||
- [Automatic XSS Protection](#automatic-xss-protection)
|
||||
- [New `set:html` and `set:text` directives](#new-sethtml-and-settext-directives)
|
||||
- [Safe access to sensitive environment variables](#safe-access-to-sensitive-environment-variables)
|
||||
- [Better builds with Vite v2.8](#better-builds-with-vite-v28)
|
||||
- [Better stability with @astro/compiler v0.11](#better-stability-with-astrocompiler-v011)
|
||||
- [Better performance with `--experimental-static-builds`](#better-performance-with---experimental-static-builds)
|
||||
- [Better build performance with `--experimental-static-builds`](#better-build-performance)
|
||||
|
||||
## Dynamic File Routes
|
||||
|
||||
|
@ -48,7 +49,7 @@ Astro v0.23 begins our migration towards automatic HTML escaping inside of Astro
|
|||
|
||||
```astro
|
||||
<!-- Examples of untrusted HTML injection -->
|
||||
<div>{`<span>Hello, trusted HTML</span>`}</div>
|
||||
<div>{`<span>Hello, dangerous HTML</span>`}</div>
|
||||
<div>{`<script>alert('oh no');</script>`}</div>
|
||||
<div>{untrustedHtml}</div>
|
||||
```
|
||||
|
@ -63,8 +64,8 @@ Two new directives are introduced to support better HTML injection when you need
|
|||
|
||||
```astro
|
||||
<!-- Examples of explicit HTML setting -->
|
||||
<div set:html={`<span>Hello, trusted HTML</span>`}></div>
|
||||
<div set:html={`<script>alert('oh no');</script>`}></div>
|
||||
<div set:html={`<span>Hello, trusted or already escaped HTML</span>`}></div>
|
||||
<div set:html={`<script>alert('oh yes');</script>`}></div>
|
||||
<div set:html={trustedOrAlreadyEscapedHtml}></div>
|
||||
```
|
||||
|
||||
|
@ -72,11 +73,28 @@ If you don't want a `<div>` wrapper, you can also use `set:html` on the Fragment
|
|||
|
||||
```
|
||||
- {`<span>Hello, dangerous HTML</span>`}
|
||||
+ <Fragment set:html={`<span>Hello, dangerous HTML</span>`} />
|
||||
+ <Fragment set:html={`<span>Hello, trusted or already escaped HTML</span>`} />
|
||||
```
|
||||
|
||||
`set:text` is also available to set the element text directly, similar to setting the `.text` property on an element in the browser. Together, these two directives give you a bit more control over the Astro output when you need it.
|
||||
|
||||
## Safe access to sensitive environment variables
|
||||
|
||||
For security, Vite only loads environment variables that are explicitly opted-in to be exposed with a `PUBLIC_` prefix. This restriction makes sense in the browser, and protects you from accidentally leaking secret tokens and values. However, it also meant that private environment variables weren't available to you at all, even locally inside of server-rendered Astro components.
|
||||
|
||||
<p>In Astro v0.23, <code>import.meta.env</code> now lets you access your private environment variables inside of Astro and anytime code renders locally or on the server. Astro will continue to protect you on the client, and only expose <code>PUBLIC_</code> variables to the frontend that ships to your users.</p>
|
||||
|
||||
```js
|
||||
// DB_PASSWORD is only available when building your site.
|
||||
// If any code tried to run this in the browser, it will be empty.
|
||||
const data = await db(import.meta.env.DB_PASSWORD);
|
||||
|
||||
// PUBLIC_POKEAPI is available anywhere, thanks to the PUBLIC_ prefix!
|
||||
const data = fetch(`${import.meta.env.PUBLIC_POKEAPI}/pokemon/squirtle`);
|
||||
```
|
||||
|
||||
See our [Environment Variables documentation](https://docs.astro.build/en/guides/environment-variables/) to learn more.
|
||||
|
||||
## Better builds with Vite v2.8
|
||||
|
||||
Astro v0.23 comes with an internal Vite upgrade that brings new features and huge stability improvements. Vite's npm package handling got a boost as well, so that more packages should work in more projects. [Check out their changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) to learn more.
|
||||
|
@ -85,7 +103,7 @@ Astro v0.23 comes with an internal Vite upgrade that brings new features and hug
|
|||
|
||||
Astro v0.23 also got a compiler upgrade which should result in noticeable performance and stability improvements across all projects. [Check out the changelog](https://github.com/withastro/compiler/releases) to learn more.
|
||||
|
||||
## Better performance with `--experimental-static-builds`
|
||||
## Better build performance
|
||||
You may have noticed the reference to `--experimental-static-build` above, and the fact that some new features are only available behind this flag. This flag is not new in v0.23, but it continues to improve as we get closer to an official release of the feature. This new "static build" strategy will soon become the default build behavior in Astro.
|
||||
|
||||
If you haven't tried the `--experimental-static-build` flag out yet in your build, please give it a try and leave us feedback in Discord. Check out our blog post [Scaling Astro to 10,000+ Pages](/blog/experimental-static-build) to learn more about this future build strategy for Astro.
|
||||
|
|
73
smoke/astro.build-main/src/scripts/defer.ts
Normal file
|
@ -0,0 +1,73 @@
|
|||
// Aha! These are not polyfills at all!
|
||||
if (window.matchMedia("(hover: hover)").matches) {
|
||||
class KonamiCode {
|
||||
enabled = false;
|
||||
keys = [
|
||||
"ArrowUp",
|
||||
"ArrowUp",
|
||||
"ArrowDown",
|
||||
"ArrowDown",
|
||||
"ArrowLeft",
|
||||
"ArrowRight",
|
||||
"ArrowLeft",
|
||||
"ArrowRight",
|
||||
"b",
|
||||
"a",
|
||||
];
|
||||
accepted = [...new Set(this.keys)];
|
||||
inputs = [];
|
||||
|
||||
constructor() {
|
||||
this.handleKey = this.handleKey.bind(this);
|
||||
document.addEventListener("keydown", this.handleKey);
|
||||
}
|
||||
|
||||
handleKey({ key }) {
|
||||
if (this.enabled) {
|
||||
this.reset();
|
||||
return;
|
||||
}
|
||||
if (!this.accepted.includes(key)) return;
|
||||
|
||||
if (this.keys[this.inputs.length] === key) {
|
||||
this.handleInput(key);
|
||||
} else {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
handleInput(key) {
|
||||
this.inputs.push(key);
|
||||
|
||||
if (this.inputs.length === 10) {
|
||||
this.handleMatch();
|
||||
}
|
||||
}
|
||||
|
||||
handleMatch() {
|
||||
this.enabled = true;
|
||||
this.enable();
|
||||
this.inputs = [];
|
||||
}
|
||||
|
||||
reset() {
|
||||
if (this.enabled) {
|
||||
this.enabled = false;
|
||||
this.disable();
|
||||
}
|
||||
if (this.inputs.length) {
|
||||
this.inputs = [];
|
||||
}
|
||||
}
|
||||
|
||||
enable() {
|
||||
document.body.classList.add("🥚");
|
||||
}
|
||||
|
||||
disable() {
|
||||
document.body.classList.remove("🥚");
|
||||
}
|
||||
}
|
||||
|
||||
const konami = new KonamiCode();
|
||||
}
|
11
smoke/astro.build-main/src/scripts/marquee.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
const checkbox = document.querySelector('#marquee-pause');
|
||||
function onChange(element) {
|
||||
const paused = element.checked;
|
||||
localStorage.setItem('astro:marquee-paused', `${paused}`);
|
||||
}
|
||||
checkbox.addEventListener('change', ({ target }) => onChange(target))
|
||||
checkbox.addEventListener('keydown', event => {
|
||||
const { key, target } = event as KeyboardEvent
|
||||
if (key !== 'Enter') return;
|
||||
onChange(target);
|
||||
})
|
|
@ -1,4 +1,5 @@
|
|||
const nav = document.querySelector("nav.main") as HTMLElement;
|
||||
const logo = document.getElementById("navlogo") as HTMLAnchorElement;
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
let isStuck = false;
|
||||
|
@ -16,3 +17,10 @@ window.addEventListener("DOMContentLoaded", () => {
|
|||
updateStuck();
|
||||
window.addEventListener("scroll", updateStuck);
|
||||
});
|
||||
|
||||
if (matchMedia("(pointer:fine)").matches) {
|
||||
logo.addEventListener("contextmenu", (event) => {
|
||||
event.preventDefault();
|
||||
window.location.href = "/press";
|
||||
})
|
||||
}
|
29
smoke/astro.build-main/src/styles/fonts.css
Normal file
|
@ -0,0 +1,29 @@
|
|||
@font-face {
|
||||
font-family: "RT Alias Medium";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local(""), url("/fonts/RTAliasMedium-Regular.woff2") format("woff2");
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "RT Alias Medium";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local(""),
|
||||
url("/fonts/RTAliasMedium-RegularOblique.woff2") format("woff2");
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "RT Alias Medium";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local(""), url("/fonts/RTAliasMedium-Bold.woff2") format("woff2");
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "RT Alias Medium";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local(""), url("/fonts/RTAliasMedium-BoldOblique.woff2") format("woff2");
|
||||
font-display: swap;
|
||||
}
|
48
smoke/astro.build-main/src/styles/tailwind.css
Normal file
|
@ -0,0 +1,48 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
/** sanitize.css makes the line-height 1.5 globally, fix this for headers */
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
line-height: 1.11;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--color-blue);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.prose :is(h2, h3, h4, h5, h6) a {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
text-decoration: none !important;
|
||||
display: inline-flex;
|
||||
}
|
||||
.prose :is(h2, h3, h4, h5, h6) a:after {
|
||||
content: "#";
|
||||
width: 1em;
|
||||
margin-left: .25em;
|
||||
color: inherit;
|
||||
opacity: 0;
|
||||
transition: opacity .2s cubic-bezier(.23,1,.32,1);
|
||||
order: 999
|
||||
}
|
||||
.prose :is(h2, h3, h4, h5, h6) a:is(:active, :visited, :hover, :focus) {
|
||||
color: var(--color-dusk)
|
||||
}
|
||||
.prose :is(h2, h3, h4, h5, h6) a:active:after,
|
||||
.prose :is(h2, h3, h4, h5, h6) a:hover:after,
|
||||
.prose :is(h2, h3, h4, h5, h6) a:focus:after {
|
||||
opacity:.6 !important;
|
||||
}
|
||||
|
||||
.text-gradient {
|
||||
background: var(--fill, var(--gradient-pop-1));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
}
|
84
smoke/astro.build-main/src/styles/variables.css
Normal file
|
@ -0,0 +1,84 @@
|
|||
:root {
|
||||
--color-tan: #f4efed;
|
||||
--color-tan-rgb: 244, 239, 237;
|
||||
--color-dawn: #f3e9fa;
|
||||
--color-dusk: #514375;
|
||||
--color-midnight: #31274a;
|
||||
--color-midnight-rgb: 49, 39, 74;
|
||||
--color-blue: #205eff;
|
||||
--color-red: #ff5050;
|
||||
--color-yellow: #ffd542;
|
||||
--color-purple: #af43ff;
|
||||
--color-pink: #fdb2b7;
|
||||
|
||||
--gradient-pop-1: linear-gradient(180deg, #205eff 0%, #c238bd 115%);
|
||||
--gradient-pop-2: repeating-linear-gradient(
|
||||
135deg,
|
||||
#ff9776 0em,
|
||||
#769cff 1em,
|
||||
#c238bd 2em,
|
||||
#ff9776 3em
|
||||
);
|
||||
--gradient-pop-3: linear-gradient(180deg, #ffb4b4 0%, #c487f0 100%);
|
||||
--gradient-pop-4: linear-gradient(
|
||||
0deg,
|
||||
#632cca -33%,
|
||||
#62289e 10%,
|
||||
#30216b 50%,
|
||||
#1f1638 100%
|
||||
);
|
||||
--gradient-pop-5: linear-gradient(
|
||||
180deg,
|
||||
#ffd542 0%,
|
||||
#ff5050 25%,
|
||||
#af43ff 100%
|
||||
);
|
||||
--gradient-mood: linear-gradient(
|
||||
180deg,
|
||||
#d8c5ef 0%,
|
||||
rgba(225, 213, 238, 0) 100%
|
||||
);
|
||||
|
||||
--shadow-sm: 0px 19px 53px 0px rgba(var(--color-midnight-rgb), 0.03),
|
||||
0px 10px 28px 0px rgba(var(--color-midnight-rgb), 0.05),
|
||||
0px 6px 16px 0px rgba(var(--color-midnight-rgb), 0.05),
|
||||
0px 3px 9px 0px rgba(var(--color-midnight-rgb), 0.075),
|
||||
0px 1px 4px 0px rgba(var(--color-midnight-rgb), 0.1);
|
||||
--shadow-md: 0px 2px 2px 0px rgba(var(--color-midnight-rgb), 0.04),
|
||||
0px 6px 5px 0px rgba(var(--color-midnight-rgb), 0.06),
|
||||
0px 15px 14px 0px rgba(var(--color-midnight-rgb), 0.08),
|
||||
0px 50px 46px 0px rgba(var(--color-midnight-rgb), 0.12);
|
||||
--shadow-xl: 0px 3px 2px 0px rgba(var(--color-midnight-rgb), 0.02),
|
||||
0px 6px 5px 0px rgba(var(--color-midnight-rgb), 0.03),
|
||||
0px 12px 10px 0px rgba(var(--color-midnight-rgb), 0.04),
|
||||
0px 22px 18px 0px rgba(var(--color-midnight-rgb), 0.04),
|
||||
0px 42px 34px 0px rgba(var(--color-midnight-rgb), 0.05),
|
||||
0px 100px 80px 0px rgba(var(--color-midnight-rgb), 0.07);
|
||||
|
||||
--blur-md: blur(10px);
|
||||
--blur-xl: blur(128px);
|
||||
|
||||
--font-base: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
||||
--font-body: var(--font-base);
|
||||
--font-display: "RT Alias Medium", var(--font-base);
|
||||
--font-mono: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
|
||||
--corner-md: 12px;
|
||||
|
||||
--size-300: clamp(0.7rem, 0.66rem + 0.2vw, 0.8rem);
|
||||
--size-400: clamp(0.88rem, 0.83rem + 0.24vw, 1rem);
|
||||
--size-500: clamp(1.09rem, 1rem + 0.47vw, 1.33rem);
|
||||
--size-600: clamp(1.37rem, 1.21rem + 0.8vw, 1.78rem);
|
||||
--size-700: clamp(1.71rem, 1.45rem + 1.29vw, 2.37rem);
|
||||
--size-800: clamp(2.14rem, 1.74rem + 1.99vw, 3.16rem);
|
||||
--size-900: clamp(2.67rem, 2.07rem + 3vw, 4.21rem);
|
||||
--size-1000: clamp(3.34rem, 2.45rem + 4.43vw, 5.61rem);
|
||||
|
||||
/* @property fallbacks */
|
||||
--border-radius: 4;
|
||||
--pixel-size: 4;
|
||||
--link-color-stop-a: #205eff;
|
||||
--link-color-stop-b: #c238bd;
|
||||
}
|
168
smoke/astro.build-main/tailwind.config.js
Normal file
|
@ -0,0 +1,168 @@
|
|||
const FONT_FAMILY_BASE = [
|
||||
"system-ui",
|
||||
"-apple-system",
|
||||
"BlinkMacSystemFont",
|
||||
"Segoe UI",
|
||||
"Roboto",
|
||||
"Oxygen",
|
||||
"Ubuntu",
|
||||
"Cantarell",
|
||||
"Open Sans",
|
||||
"Helvetica Neue",
|
||||
"sans-serif",
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
corePlugins: {
|
||||
container: false,
|
||||
},
|
||||
content: ["./src/**/*.{astro,html,js,jsx,svelte,ts,tsx,vue}"],
|
||||
theme: {
|
||||
colors: {
|
||||
white: "#fff",
|
||||
black: "#000",
|
||||
transparent: "transparent",
|
||||
tan: "#f4efed",
|
||||
dawn: "#f3e9fa",
|
||||
dusk: "#514375",
|
||||
midnight: "#31274a",
|
||||
blue: "#205eff",
|
||||
red: "#ff5050",
|
||||
yellow: "#ffd542",
|
||||
purple: "#af43ff",
|
||||
pink: "#fdb2b7",
|
||||
pop: {
|
||||
1: "linear-gradient(180deg, #205eff 0%, #c238bd 115%)",
|
||||
},
|
||||
},
|
||||
fontFamily: {
|
||||
body: FONT_FAMILY_BASE,
|
||||
display: ["RT Alias Medium", ...FONT_FAMILY_BASE],
|
||||
mono: [
|
||||
"Menlo",
|
||||
"Monaco",
|
||||
"Lucida Console",
|
||||
"Liberation Mono",
|
||||
"DejaVu Sans Mono",
|
||||
"Bitstream Vera Sans Mono",
|
||||
"Courier New",
|
||||
"monospace",
|
||||
],
|
||||
},
|
||||
fontSize: {
|
||||
xs: "clamp(0.7rem, 0.66rem + 0.2vw, 0.8rem)",
|
||||
sm: "clamp(0.88rem, 0.83rem + 0.24vw, 1rem)",
|
||||
base: "clamp(1.09rem, 1rem + 0.47vw, 1.33rem)",
|
||||
lg: "clamp(1.37rem, 1.21rem + 0.8vw, 1.78rem)",
|
||||
xl: "clamp(1.71rem, 1.45rem + 1.29vw, 2.37rem)",
|
||||
"2xl": "clamp(2.14rem, 1.74rem + 1.99vw, 3.16rem)",
|
||||
"3xl": "clamp(2.67rem, 2.07rem + 3vw, 4.21rem)",
|
||||
"4xl": "clamp(3.34rem, 2.45rem + 4.43vw, 5.61rem)",
|
||||
},
|
||||
extend: {
|
||||
typography: ({ theme }) => {
|
||||
const headings = {
|
||||
"h1, h2, h3, h4, h5, h6": {
|
||||
fontFamily: "var(--font-display)",
|
||||
fontWeight: "bold",
|
||||
lineHeight: 1.1,
|
||||
textAlign: "inherit"
|
||||
},
|
||||
h1: {
|
||||
fontSize: theme("fontSize.3xl"),
|
||||
},
|
||||
h2: {
|
||||
fontSize: theme("fontSize.2xl"),
|
||||
},
|
||||
h3: {
|
||||
fontSize: theme("fontSize.xl"),
|
||||
},
|
||||
h4: {
|
||||
fontSize: theme("fontSize.lg"),
|
||||
},
|
||||
h5: {
|
||||
fontSize: theme("fontSize.sm"),
|
||||
},
|
||||
h6: {
|
||||
fontSize: theme("fontSize.xs"),
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
DEFAULT: {
|
||||
css: {
|
||||
maxWidth: '75ch',
|
||||
fontSize: "var(--size-500)",
|
||||
lineHeight: "1.5",
|
||||
// override @tailwindcss/typography colors
|
||||
"--tw-prose-body": theme("colors.midnight"),
|
||||
"--tw-prose-headings": theme("colors.dusk"),
|
||||
"--tw-prose-links": theme("colors.blue"),
|
||||
"--tw-prose-code": theme("colors.purple"),
|
||||
"--tw-prose-pre-bg":
|
||||
"linear-gradient(to bottom,var(--color-midnight),#1f1638)",
|
||||
"--tw-prose-pre-code": theme("colors.white"),
|
||||
"--tw-prose-bullets": "rgba(var(--color-midnight-rgb), 0.5)",
|
||||
":focus-visible": {
|
||||
outline: "2px dashed var(--color-blue)",
|
||||
},
|
||||
...headings,
|
||||
a: {
|
||||
textDecoration: "none",
|
||||
fontWeight: 400,
|
||||
wordBreak: "break-word",
|
||||
"&:hover": {
|
||||
textDecoration: "underline",
|
||||
},
|
||||
"> code": {
|
||||
color: "var(--tw-prose-code)",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sm: {
|
||||
...headings,
|
||||
},
|
||||
md: {
|
||||
...headings,
|
||||
},
|
||||
lg: {
|
||||
...headings,
|
||||
},
|
||||
xl: {
|
||||
...headings,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
require("@tailwindcss/typography"),
|
||||
require("@tailwindcss/aspect-ratio"),
|
||||
function ({ addComponents, theme }) {
|
||||
addComponents({
|
||||
".container": {
|
||||
maxWidth: "40rem",
|
||||
marginLeft: "auto",
|
||||
marginRight: "auto",
|
||||
"@screen md": { maxWidth: "50rem" },
|
||||
"@screen lg": { maxWidth: "62rem" },
|
||||
"@screen xl": { maxWidth: "80rem" },
|
||||
"@screen 2xl": { maxWidth: "90rem" },
|
||||
},
|
||||
".head-md": {
|
||||
fontFamily: theme("fontFamily.display"),
|
||||
fontSize: theme("fontSize.xl"),
|
||||
letterSpacing: -0.5,
|
||||
lineHeight: 1.2,
|
||||
fontWeight: "bold"
|
||||
},
|
||||
".body-md": {
|
||||
fontFamily: theme("fontFamily.body"),
|
||||
fontSize: theme("fontSize.body"),
|
||||
lineHeight: 1.3,
|
||||
}
|
||||
});
|
||||
},
|
||||
],
|
||||
};
|
|
@ -5,16 +5,22 @@ if (!process.env.GITHUB_TOKEN) {
|
|||
throw new Error('GITHUB_TOKEN env variable must be set to run.');
|
||||
}
|
||||
async function main() {
|
||||
function loginIsUniq(...lists) {
|
||||
return function withUser(user) {
|
||||
return !lists.some(list => list.some(a => a.login === user.login))
|
||||
}
|
||||
}
|
||||
|
||||
const [staff, _l3, _l2, _l1] = await Promise.all([
|
||||
fetch('https://api.github.com/orgs/withastro/teams/staff/members', {headers: {Authorization: 'token ' + process.env.GITHUB_TOKEN}}).then(r => r.json()),
|
||||
fetch('https://api.github.com/orgs/withastro/teams/maintainers-core/members', {headers: {Authorization: 'token ' + process.env.GITHUB_TOKEN}}).then(r => r.json()),
|
||||
fetch('https://api.github.com/orgs/withastro/teams/maintainers/members', {headers: {Authorization: 'token ' + process.env.GITHUB_TOKEN}}).then(r => r.json()),
|
||||
fetch('https://api.github.com/repos/withastro/astro/contributors?per_page=100', {headers: {Authorization: 'token ' + process.env.GITHUB_TOKEN}}).then(r => r.json()),
|
||||
]);
|
||||
const l3 = _l3.filter((a) => !staff.some(b => b.login === a.login));
|
||||
const l2 = _l2.filter((a) => !_l3.some(b => b.login === a.login));
|
||||
const l1 = _l1.filter((a) => !_l2.some(b => b.login === a.login));
|
||||
|
||||
|
||||
const l3 = _l3.filter(loginIsUniq(staff));
|
||||
const l2 = _l2.filter(loginIsUniq(staff, l3));
|
||||
const l1 = _l1.filter(loginIsUniq(staff, l3, l2));
|
||||
|
||||
fs.writeFileSync('src/data/contributors.json', JSON.stringify({staff, l3, l2, l1}));
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
"version": "0.0.7",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"dev": "astro dev --experimental-static-build",
|
||||
"start": "astro dev --experimental-static-build",
|
||||
"build": "astro build --experimental-static-build",
|
||||
"preview": "astro preview",
|
||||
"format": "prettier -w .",
|
||||
"lint": "run-p --aggregate-output lint:linkcheck",
|
||||
|
@ -17,7 +17,7 @@
|
|||
"lint:linkcheck:remote": "blc -ro --user-agent 'broken-link-checker/0.7.8' 'https://docs.astro.build/'"
|
||||
},
|
||||
"devDependencies": {
|
||||
"astro": "0.23.0-next.10",
|
||||
"astro": "0.23.3",
|
||||
"broken-link-checker": "^0.7.8",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"pa11y-ci": "^3.0.1",
|
||||
|
@ -25,7 +25,8 @@
|
|||
"prettier-plugin-astro": "^0.0.12"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docsearch/react": "^3.0.0-alpha.50"
|
||||
"@docsearch/react": "^3.0.0-alpha.50",
|
||||
"sass": "^1.49.8"
|
||||
},
|
||||
"volta": {
|
||||
"node": "14.18.1"
|
||||
|
|
|
@ -244,12 +244,10 @@ table {
|
|||
}
|
||||
|
||||
/* Zebra striping */
|
||||
tr:nth-of-type(odd) {
|
||||
tbody tr:nth-of-type(odd) {
|
||||
background: var(--theme-bg-hover);
|
||||
}
|
||||
th {
|
||||
background: var(--color-black);
|
||||
color: var(--theme-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
td,
|
||||
|
|
|
@ -18,13 +18,13 @@ const previous = index !== -1 ? (index === 0 ? null : links[index - 1]) : null;
|
|||
<section class="main-section">
|
||||
<h1 class="content-title" id="overview">{title}</h1>
|
||||
{headers && (
|
||||
<nav class="block sm:hidden">
|
||||
<nav class="block sm-hidden">
|
||||
<TableOfContents client:media="(max-width: 50em)" headers={headers} />
|
||||
</nav>
|
||||
)}
|
||||
<slot />
|
||||
</section>
|
||||
<nav class="block sm:hidden">
|
||||
<nav class="block sm-hidden">
|
||||
<MoreMenu editHref={githubEditUrl} />
|
||||
</nav>
|
||||
{(previous || next) && (
|
||||
|
@ -66,7 +66,7 @@ const previous = index !== -1 ? (index === 0 ? null : links[index - 1]) : null;
|
|||
}
|
||||
|
||||
@media (min-width: 50em) {
|
||||
.sm\:hidden {
|
||||
.sm-hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,19 +2,19 @@ export const SIDEBAR = {
|
|||
en: [
|
||||
{ text: 'Setup', header: true },
|
||||
{ text: 'Getting Started', link: 'en/getting-started' },
|
||||
{ text: 'Quickstart', link: 'en/quick-start' },
|
||||
{ text: 'Installation', link: 'en/installation' },
|
||||
{ text: 'Migration Guide', link: 'en/migrate' },
|
||||
{ text: 'Themes', link: 'en/themes' },
|
||||
{ text: 'Astro vs. X', link: 'en/comparing-astro-vs-other-tools' },
|
||||
{ text: 'Integrations', link: `en/integrations/integrations`},
|
||||
|
||||
{ text: 'Basics', header: true },
|
||||
{ text: 'Project Structure', link: 'en/core-concepts/project-structure' },
|
||||
{ text: 'Component Syntax', link: 'en/core-concepts/astro-components' },
|
||||
{ text: 'Components', link: 'en/core-concepts/astro-components' },
|
||||
{ text: 'Pages', link: 'en/core-concepts/astro-pages' },
|
||||
{ text: 'Layouts', link: 'en/core-concepts/layouts' },
|
||||
{ text: 'Routing', link: 'en/core-concepts/routing' },
|
||||
{ text: 'Partial Hydration', link: 'en/core-concepts/component-hydration' },
|
||||
{ text: 'Astro vs. X', link: 'en/comparing-astro-vs-other-tools' },
|
||||
|
||||
{ text: 'Guides', header: true },
|
||||
{ text: 'Styling & CSS', link: 'en/guides/styling' },
|
||||
|
@ -26,6 +26,7 @@ export const SIDEBAR = {
|
|||
{ text: 'Supported Imports', link: 'en/guides/imports' },
|
||||
{ text: 'Aliases', link: 'en/guides/aliases' },
|
||||
{ text: 'Environment Variables', link: 'en/guides/environment-variables' },
|
||||
{ text: 'Manual Setup', link: 'en/guides/manual-setup' },
|
||||
{ text: 'Deploy to the web', link: 'en/guides/deploy' },
|
||||
{ text: 'Publish to npm', link: 'en/guides/publish-to-npm' },
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
layout: ~/layouts/MainLayout.astro
|
||||
title: Comparing Astro
|
||||
title: Astro vs. X
|
||||
description: Comparing Astro with other static site generators like Gatsby, Next.js, Nuxt, Hugo, Eleventy, and more.
|
||||
---
|
||||
|
||||
|
|
|
@ -1,382 +1,146 @@
|
|||
---
|
||||
layout: ~/layouts/MainLayout.astro
|
||||
title: Astro Components
|
||||
title: Components
|
||||
description: An intro to the .astro component syntax.
|
||||
---
|
||||
|
||||
**Astro Components** (files ending with `.astro`) are the foundation of server-side templating in Astro. Think of the Astro component syntax as HTML enhanced with JavaScript.
|
||||
**Astro components** are the basic building blocks of any Astro project.
|
||||
|
||||
Learning a new syntax can feel intimidating, so we carefully designed the Astro component syntax to feel as familiar to web developers as possible. It borrows heavily from patterns you likely already know: components, frontmatter, props, and JSX expressions. We're confident that this guide will have you writing Astro components in no time, especially if you are already familiar with HTML & JavaScript.
|
||||
Astro component syntax is a superset of HTML. The syntax was designed to feel familiar to anyone with experience writing HTML or JSX, and adds support for including components and JavaScript expressions. You can spot an Astro component by its file extension: `.astro`.
|
||||
|
||||
## Syntax Overview
|
||||
Astro components are extremely flexible. Often, an Astro component will contain some **reusable UI on the page**, like a header or a profile card. At other times, an Astro component may contain a smaller snippet of HTML, like a collection of common `<meta>` tags that make SEO easy to work with. Astro components can even contain an entire page layout.
|
||||
|
||||
A single `.astro` file represents a single Astro component in your project. This pattern is known as a **Single-File Component (SFC)**. Both Svelte (`.svelte`) and Vue (`.vue`) also follow this pattern.
|
||||
The most important thing to know about Astro components is that they **render to HTML during your build.** Even if you run JavaScript code inside of your components, it will all run ahead-of-time, stripped from the final page that you send to your users. The result is a faster site, with zero JavaScript footprint added by default.
|
||||
|
||||
Below is a walk-through of the different pieces and features of the Astro component syntax. You can read it start-to-finish, or jump between sections.
|
||||
|
||||
### HTML Template
|
||||
## Component Overview
|
||||
|
||||
Astro component syntax is a superset of HTML. **If you know HTML, you already know enough to write your first Astro component.**
|
||||
An Astro component is made up of two main parts: the **Component Script** and the **Component Template**. Each part performs a different job, but together they aim to provide a framework that is both easy to use and expressive enough to handle whatever you might want to build.
|
||||
|
||||
For example, this three-line file is a valid Astro component:
|
||||
```astro
|
||||
---
|
||||
// Component Script (JavaScript)
|
||||
---
|
||||
<!-- Component Template (HTML + JS Expressions) -->
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- Example1.astro - Static HTML is a valid Astro component! -->
|
||||
<div class="example-1">
|
||||
<h1>Hello world!</h1>
|
||||
You can use components inside of other components, to build more and more advanced UI. For example, a `Button` component could be used to create a `ButtonGroup` component like so:
|
||||
|
||||
```astro
|
||||
---
|
||||
// Example: ButtonGroup.astro
|
||||
import Button from './Button.astro';
|
||||
---
|
||||
<div>
|
||||
<Button title="Button 1" />
|
||||
<Button title="Button 2" />
|
||||
<Button title="Button 3" />
|
||||
</div>
|
||||
```
|
||||
|
||||
An Astro component represents some snippet of HTML in your project. This can be a reusable component, or an entire page of HTML including `<html>`, `<head>` and `<body>` elements. See our guide on [Astro Pages](/en/core-concepts/astro-pages) to learn how to build your first full HTML page with Astro.
|
||||
|
||||
**Every Astro component must include an HTML template.** While you can enhance your component in several ways (see below), at the end of the day it’s the HTML template that dictates what your rendered Astro component will look like.
|
||||
### The Component Script
|
||||
|
||||
Astro uses a code fence (`---`) to identify the component script in your Astro component. If you've ever written Markdown before, you may already be familiar with a similar concept called *front matter.* Astro's idea of a component script was directly inspired by this concept.
|
||||
|
||||
You can use the component script to write any JavaScript code that you need to render your template. This can include:
|
||||
|
||||
- Importing other Astro components
|
||||
- Importing other framework components, like React
|
||||
- Importing data, like a JSON file
|
||||
- fetching content from an API or database
|
||||
- creating variables that you will reference in your template
|
||||
|
||||
```astro
|
||||
---
|
||||
import SomeAstroComponent from '../components/SomeAstroComponent.astro';
|
||||
import SomeReactComponent from '../components/SomeReactComponent.jsx';
|
||||
import someData from '../data/pokemon.json';
|
||||
|
||||
// Access passed-in component props, like `<X title="Hello, World" />`
|
||||
const {title} = Astro.props;
|
||||
// Fetch external data, even from a private API or database
|
||||
const data = await fetch('SOME_SECRET_API_URL/users').then(r => r.json());
|
||||
---
|
||||
<!-- Your template here! -->
|
||||
```
|
||||
|
||||
The code fence is designed to guarantee that the JavaScript that you write in it is "fenced in." It won't escape into your frontend application, or fall into your users hands. You can safely write code here that is expensive or sensitive (like a call to your private database) without worrying about it ever ending up in your user's browser.
|
||||
|
||||
>💡 *You can even write TypeScript in your component script!*
|
||||
|
||||
### The Component Template
|
||||
|
||||
Below the component script, sits the component template. The component template decides the HTML output of your component.
|
||||
|
||||
If you write plain HTML here, your component will render that HTML in any Astro page it is imported and used.
|
||||
|
||||
However, Astro's component template syntax also supports **JavaScript expressions**, **imported components** and **special Astro directives**. Data and values defined (at page build time) in the component script can be used in the component template to produce dynamically-created HTML.
|
||||
|
||||
```astro
|
||||
---
|
||||
// Your component script here!
|
||||
import ReactPokemonComponent from '../components/ReactPokemonComponent.jsx';
|
||||
const myFavoritePokemon = [/* ... */];
|
||||
---
|
||||
<!-- HTML comments supported! -->
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
<!-- Use props and other variables from the component script: -->
|
||||
<p>My favorite pokemon is: {Astro.props.title}</p>
|
||||
|
||||
<!-- Include other components with a `client:` directive to hydrate: -->
|
||||
<ReactPokemonComponent client:visible />
|
||||
|
||||
<!-- Mix HTML with JavaScript expressions, similar to JSX: -->
|
||||
<ul>
|
||||
{myFavoritePokemon.map((data) => <li>{data.name}</li>)}
|
||||
<ul>
|
||||
|
||||
|
||||
```
|
||||
|
||||
### CSS Styles
|
||||
|
||||
CSS rules inside of a `<style>` tag are automatically scoped to that component. That means that you can reuse class names across multiple components, without worrying about conflicts. Styles are automatically extracted and optimized in the final build so that you don't need to worry about style loading.
|
||||
CSS `<style>` tags are also supported inside of the component template.
|
||||
|
||||
For best results, you should only have one `<style>` tag per-Astro component. This isn't necessarily a limitation, but it will often result in better-optimized CSS in your final build. When you're working with pages, the `<style>` tag can go nested inside of your page `<head>`. For standalone components, the `<style>` tag can go at the top-level of your template.
|
||||
They can be used to style your components, and all style rules are automatically scoped to the component itself to prevent CSS conflicts in large apps.
|
||||
|
||||
```html
|
||||
<!-- Astro Component CSS example -->
|
||||
```astro
|
||||
---
|
||||
// Your component script here!
|
||||
---
|
||||
<style>
|
||||
.circle {
|
||||
background-color: red;
|
||||
border-radius: 999px;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
/* scoped to the component, other H1s on the page remain the same */
|
||||
h1 { color: red }
|
||||
</style>
|
||||
<div class="circle"></div>
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- Astro Page CSS example -->
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
...;
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
...
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
<h1>Hello, world!</h1>
|
||||
```
|
||||
|
||||
Using `<style global>` will skip automatic scoping for every CSS rule in the `<style>` block. This escape hatch should be avoided if possible but can be useful if, for example, you need to modify styling for HTML elements added by an external library.
|
||||
> ⚠️ The styles defined here apply only to content written directly in the component's own component template. Children, and any imported components will **not** be styled by default.
|
||||
|
||||
Sass (an alternative to CSS) is also available via `<style lang="scss">`.
|
||||
📚 See our [Styling Guide](/en/guides/styling) for more information on applying styles.
|
||||
|
||||
📚 Read our full guide on [Component Styling](/en/guides/styling) to learn more.
|
||||
### Client-Side Scripts
|
||||
|
||||
### Frontmatter Script
|
||||
|
||||
To build dynamic components, we introduce the idea of a frontmatter component script. [Frontmatter](https://jekyllrb.com/docs/front-matter/) is a common pattern in Markdown, where some config/metadata is contained inside a code fence (`---`) at the top of the file. Astro does something similar, but with full support for JavaScript & TypeScript in your components.
|
||||
|
||||
Remember that Astro is a server-side templating language, so your component script will run during the build but only the HTML is rendered to the browser. To send JavaScript to the browser, you can use a `<script>` tag in your HTML template or [convert your component to use a frontend framework](/en/core-concepts/component-hydration) like React, Svelte, Vue, etc.
|
||||
To send JavaScript to the browser without [using a framework component](/en/core-concepts/component-hydration) (React, Svelte, Vue, Preact, Solid...) you can use a `<script>` tag in your Astro component body.
|
||||
|
||||
```astro
|
||||
---
|
||||
// Anything inside the `---` code fence is your component script.
|
||||
// This JavaScript code runs at build-time.
|
||||
// See below to learn more about what you can do.
|
||||
// Tip: TypeScript is also supported out-of-the-box!
|
||||
const thisWorks: number = 42;
|
||||
console.log('This runs at build-time, is visible in the CLI output', thisWorks);
|
||||
// Your component script here!
|
||||
---
|
||||
<div class="example-1">
|
||||
<h1>Hello world!</h1>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Component Imports
|
||||
|
||||
An Astro component can reuse other Astro components inside of its HTML template. This becomes the foundation of our component system: build new components and then reuse them across your project.
|
||||
|
||||
To use an Astro component in your template, you first need to import it in the frontmatter component script. An Astro component is always the file’s default import.
|
||||
|
||||
Once imported, you can use it like any other HTML element in your template. Note that an Astro component **MUST** begin with an uppercase letter. Astro will use this to distinguish between native HTML elements (`form`, `input`, etc.) and your custom Astro components.
|
||||
|
||||
```astro
|
||||
---
|
||||
// Import your components in your component script...
|
||||
import SomeComponent from './SomeComponent.astro';
|
||||
---
|
||||
<!-- ... then use them in your HTML! -->
|
||||
<div>
|
||||
<SomeComponent />
|
||||
</div>
|
||||
```
|
||||
|
||||
📚 You can also import and use components from other frontend frameworks like React, Svelte, and Vue. Read our guide on [Component Hydration](/en/core-concepts/component-hydration) to learn more.
|
||||
|
||||
### Dynamic JSX Expressions
|
||||
|
||||
Instead of inventing our own custom syntax for dynamic templating, we give you direct access to JavaScript values inside of your HTML, using something that feels just like [JSX](https://reactjs.org/docs/introducing-jsx.html).
|
||||
|
||||
Astro components can define local variables inside of the Frontmatter script. Any script variables are then automatically available in the HTML template below.
|
||||
|
||||
#### Dynamic Values
|
||||
|
||||
```astro
|
||||
---
|
||||
const name = "Your name here";
|
||||
---
|
||||
<div>
|
||||
<h1>Hello {name}!</h1>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### Dynamic Attributes
|
||||
|
||||
```astro
|
||||
---
|
||||
const name = "Your name here";
|
||||
---
|
||||
<div>
|
||||
<div data-name={name}>Attribute expressions supported</div>
|
||||
<div data-hint={`Use JS template strings to mix ${"variables"}.`}>So good!</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### Dynamic HTML
|
||||
|
||||
```astro
|
||||
---
|
||||
const items = ["Dog", "Cat", "Platipus"];
|
||||
---
|
||||
<ul>
|
||||
{items.map((item) => (
|
||||
<li>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
```
|
||||
|
||||
### Component Props
|
||||
|
||||
An Astro component can define and accept props. Props are available on the `Astro.props` global in your frontmatter script.
|
||||
|
||||
```astro
|
||||
---
|
||||
// Example: <SomeComponent greeting="(Optional) Hello" name="Required Name" />
|
||||
const { greeting = 'Hello', name } = Astro.props;
|
||||
---
|
||||
<div>
|
||||
<h1>{greeting}, {name}!</h1>
|
||||
</div>
|
||||
```
|
||||
|
||||
You can define your props with TypeScript by exporting a `Props` type interface. Astro will automatically pick up any exported `Props` interface and give type warnings/errors for your project.
|
||||
|
||||
Make sure to keep all `import` and `export` statements at the top of the component, before any other JavaScript or TypeScript logic!
|
||||
|
||||
```astro
|
||||
---
|
||||
// include any `import` and `export` statements first
|
||||
// Example: <SomeComponent /> (WARNING: "name" prop is required)
|
||||
export interface Props {
|
||||
name: string;
|
||||
greeting?: string;
|
||||
}
|
||||
|
||||
// with `import`s and `export`s out of the way, include the rest of the component logic here
|
||||
const { greeting = 'Hello', name } = Astro.props;
|
||||
---
|
||||
<div>
|
||||
<h1>{greeting}, {name}!</h1>
|
||||
</div>
|
||||
```
|
||||
|
||||
You can then pass the component props like this:
|
||||
|
||||
```astro
|
||||
---
|
||||
// SomeOtherComponent.astro
|
||||
import SomeComponent from "./SomeComponent.astro";
|
||||
let firstName = "world!";
|
||||
---
|
||||
<SomeComponent name={firstName}/>
|
||||
```
|
||||
|
||||
### Slots
|
||||
|
||||
`.astro` files use the [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot) tag to enable component composition. Coming from React or Preact, this is the same concept as `children`. You can think of the `<slot>` element as a placeholder for markup which will be passed in from outside of the component.
|
||||
|
||||
```astro
|
||||
<!-- Example: MyComponent.astro -->
|
||||
<div id="my-component">
|
||||
<slot /> <!-- children will go here -->
|
||||
</div>
|
||||
|
||||
<!-- Usage -->
|
||||
<MyComponent>
|
||||
<h1>Hello world!</h1>
|
||||
</MyComponent>
|
||||
```
|
||||
|
||||
Note that if the `<slot>` tag is not used in the HTML template, any children passed to the component will not be rendered.
|
||||
|
||||
Slots become even more powerful when using **named slots**. Rather than a single `<slot>` element which renders _all_ children, named slots allow you to specify multiple places where children should be placed.
|
||||
|
||||
> **Note:** The `slot` attribute is not restricted to plain HTML, components can use `slot` as well!
|
||||
|
||||
```astro
|
||||
<!-- Example: MyComponent.astro -->
|
||||
<div id="my-component">
|
||||
<header>
|
||||
<!-- children with the `slot="header"` attribute will go here -->
|
||||
<slot name="header" />
|
||||
</header>
|
||||
<main>
|
||||
<!-- children without a `slot` (or with the `slot="default"`) attribute will go here -->
|
||||
<slot />
|
||||
</main>
|
||||
<footer>
|
||||
<!-- children with the `slot="footer"` attribute will go here -->
|
||||
<slot name="footer" />
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- Usage -->
|
||||
<MyComponent>
|
||||
<h1 slot="header">Hello world!</h1>
|
||||
<p>Lorem ipsum ...</p>
|
||||
<FooterComponent slot="footer" />
|
||||
</MyComponent>
|
||||
```
|
||||
|
||||
Slots can also render **fallback content**. When there are no matching children passed to a `<slot>`, a `<slot>` element will render its own placeholder children.
|
||||
|
||||
```astro
|
||||
<!-- MyComponent.astro -->
|
||||
<div id="my-component">
|
||||
<slot>
|
||||
<h1>I will render when this slot does not have any children!</h1>
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<!-- Usage -->
|
||||
<MyComponent />
|
||||
```
|
||||
|
||||
### Fragments & Multiple Elements
|
||||
|
||||
An Astro component template can render as many top-level elements as you'd like. Unlike other UI component frameworks, you don't need to wrap everything in a single `<div>` if you'd prefer not to.
|
||||
|
||||
```html
|
||||
<!-- An Astro component can contain multiple top-level HTML elements: -->
|
||||
<div id="a" />
|
||||
<div id="b" />
|
||||
<div id="c" />
|
||||
```
|
||||
|
||||
When working inside a JSX expression, however, you must wrap multiple elements inside of a **Fragment**. Fragments let you render a set of elements without adding extra nodes to the DOM. This is required in JSX expressions because of a limitation of JavaScript: You can never `return` more than one thing in a JavaScript function or expression. Using a Fragment solves this problem.
|
||||
|
||||
A Fragment must open with `<>` and close with `</>`. Don't worry if you forget this, Astro’s compiler will warn you that you need to add one.
|
||||
|
||||
> **Note:** Astro also supports opening a fragment with `<Fragment>` and closing it with `</Fragment>` if you prefer to use that syntax.
|
||||
|
||||
```astro
|
||||
---
|
||||
const items = ["Dog", "Cat", "Platipus"];
|
||||
---
|
||||
<ul>
|
||||
{items.map((item) => (
|
||||
<>
|
||||
<li>Red {item}</li>
|
||||
<li>Blue {item}</li>
|
||||
<li>Green {item}</li>
|
||||
</>
|
||||
))}
|
||||
</ul>
|
||||
```
|
||||
|
||||
### Hoisted scripts
|
||||
|
||||
By default Astro does not make any assumptions on how you want scripts to be served, so if you add a `<script>` tag in a page or a component it will be left alone.
|
||||
|
||||
However if you'd like all of your scripts to be hoisted out of components and moved to the top of the page, and then later bundled together in production, you can achieve this with hoisted scripts.
|
||||
|
||||
A **hoisted script** looks like this:
|
||||
|
||||
```astro
|
||||
<script hoist>
|
||||
// An inline script
|
||||
<script>
|
||||
document.querySelector('h1').style.color = 'red';
|
||||
</script>
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
```
|
||||
|
||||
Or it can link to an external JavaScript file:
|
||||
|
||||
```astro
|
||||
<script src={Astro.resolve('./my-component.js')} hoist></script>
|
||||
```
|
||||
## Next Steps
|
||||
|
||||
A hoisted script can be within a page or a component, and no matter how many times the component is used, the script will only be added once:
|
||||
📚 Read about [Astro's built-in components](https://docs.astro.build/en/reference/builtin-components/).
|
||||
|
||||
```astro
|
||||
---
|
||||
import TwitterTimeline from '../components/TwitterTimeline.astro';
|
||||
---
|
||||
|
||||
<-- The script will only be injected into the head once. -->
|
||||
<TwitterTimeline />
|
||||
<TwitterTimeline />
|
||||
<TwitterTimeline />
|
||||
```
|
||||
|
||||
## Comparing `.astro` versus `.jsx`
|
||||
|
||||
`.astro` files can end up looking very similar to `.jsx` files, but there are a few key differences. Here’s a comparison between the two formats.
|
||||
|
||||
| Feature | Astro | JSX |
|
||||
| ---------------------------- | ---------------------------------------------------------- | -------------------------------------------------- |
|
||||
| File extension | `.astro` | `.jsx` or `.tsx` |
|
||||
| User-Defined Components | `<Capitalized>` | `<Capitalized>` |
|
||||
| Expression Syntax | `{}` | `{}` |
|
||||
| Spread Attributes | `{...props}` | `{...props}` |
|
||||
| Boolean Attributes | `autocomplete` === `autocomplete={true}` | `autocomplete` === `autocomplete={true}` |
|
||||
| Inline Functions | `{items.map(item => <li>{item}</li>)}` | `{items.map(item => <li>{item}</li>)}` |
|
||||
| IDE Support | WIP - [VS Code][code-ext] | Phenomenal |
|
||||
| Requires JS import | No | Yes, `jsxPragma` (`React` or `h`) must be in scope |
|
||||
| Fragments | Automatic top-level, `<Fragment>` or `<>` inside functions | Wrap with `<Fragment>` or `<>` |
|
||||
| Multiple frameworks per-file | Yes | No |
|
||||
| Modifying `<head>` | Just use `<head>` | Per-framework (`<Head>`, `<svelte:head>`, etc) |
|
||||
| Comment Style | `<!-- HTML -->` | `{/_ JavaScript _/} |
|
||||
| Special Characters | ` ` | ` ` |
|
||||
| Attributes | `dash-case` | `camelCase` |
|
||||
|
||||
## URL resolution
|
||||
|
||||
It’s important to note that Astro **won't** transform HTML references for you. For example, consider an `<img>` tag with a relative `src` attribute inside `src/pages/about.astro`:
|
||||
|
||||
```html
|
||||
<!-- ❌ Incorrect: will try and load `/about/thumbnail.png` -->
|
||||
<img src="./thumbnail.png" />
|
||||
```
|
||||
|
||||
Since `src/pages/about.astro` will build to `/about/index.html`, you may not have expected that image to live at `/about/thumbnail.png`. So to fix this, choose either of two options:
|
||||
|
||||
#### Option 1: Absolute URLs
|
||||
|
||||
```html
|
||||
<!-- ✅ Correct: references public/thumbnail.png -->
|
||||
<img src="/thumbnail.png" />
|
||||
```
|
||||
|
||||
The recommended approach is to place files within `public/*`. This references a file at `public/thumbnail.png`, which will resolve to `/thumbnail.png` at the final build (since `public/` ends up at `/`).
|
||||
|
||||
#### Option 2: Asset import references
|
||||
|
||||
```astro
|
||||
---
|
||||
// ✅ Correct: references src/thumbnail.png
|
||||
import thumbnailSrc from './thumbnail.png';
|
||||
---
|
||||
|
||||
<img src={thumbnailSrc} />
|
||||
```
|
||||
|
||||
If you'd prefer to organize assets alongside Astro components, you may import the file in JavaScript inside the component script. This works as intended but this makes `thumbnail.png` harder to reference in other parts of your app, as its final URL isn't easily-predictable (unlike assets in `public/*`, where the final URL is guaranteed to never change).
|
||||
|
||||
[code-ext]: https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode
|
||||
📚 Learn about using [JavaScript framework components](https://docs.astro.build/en/core-concepts/component-hydration/) in your Astro project.
|
|
@ -1,134 +1,84 @@
|
|||
---
|
||||
layout: ~/layouts/MainLayout.astro
|
||||
title: Pages
|
||||
description: An intro to Astro pages, components that function as full pages.
|
||||
description: An introduction to Astro pages
|
||||
---
|
||||
|
||||
**Pages** are a special type of [Astro Component](/en/core-concepts/astro-components) that handle routing, data loading, and templating for each page of your website. You can think of them like any other Astro component, just with extra responsibilities.
|
||||
**Pages** are a special type of [Astro component](/en/core-concepts/astro-components) that live in the `src/pages/` subdirectory. They are responsible for handling routing, data loading, and overall page layout for every HTML page in your website.
|
||||
|
||||
Astro also supports Markdown for content-heavy pages, like blog posts and documentation. See [Markdown Content](/en/guides/markdown-content) for more information on writing pages with Markdown.
|
||||
### File-based routing
|
||||
|
||||
## File-based Routing
|
||||
Astro leverages a routing strategy called **file-based routing.** Every `.astro` file in your `src/pages` directory becomes a page on your site, creating a URL route based on the file path inside of the directory.
|
||||
|
||||
Astro uses Pages to do something called **file-based routing.** Every file in your `src/pages` directory becomes a page on your site, using the file name to decide the final route.
|
||||
📚 Read more about [Routing in Astro](/en/core-concepts/routing)
|
||||
|
||||
Astro Components (`.astro`) and Markdown Files (`.md`) are the only supported formats for pages. Other page types (like a `.jsx` React component) are not supported, but you can use anything as a UI component inside of an `.astro` page to achieve a similar result.
|
||||
### Page HTML
|
||||
|
||||
```
|
||||
src/pages/index.astro -> mysite.com/
|
||||
src/pages/about.astro -> mysite.com/about
|
||||
src/pages/about/index.astro -> mysite.com/about
|
||||
src/pages/about/me.astro -> mysite.com/about/me
|
||||
src/pages/posts/1.md -> mysite.com/posts/1
|
||||
```
|
||||
|
||||
## Page Templating
|
||||
|
||||
All Astro components are responsible for returning HTML. Astro Pages return HTML as well, but have the unique responsibility of returning a full `<html>...</html>` page response, including `<head>` ([MDN<span class="sr-only">- head</span>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)) and `<body>` ([MDN<span class="sr-only">- body</span>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body)).
|
||||
|
||||
`<!doctype html>` is optional, and will be added automatically.
|
||||
Astro Pages must return a full `<html>...</html>` page response, including `<head>` and `<body>`. (`<!doctype html>` is optional, and will be added automatically.)
|
||||
|
||||
```astro
|
||||
---
|
||||
// Example: HTML page skeleton
|
||||
// Example: src/pages/index.astro
|
||||
---
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Document title</title>
|
||||
<title>My Homepage</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello, world!</h1>
|
||||
<h1>Welcome to my website!</h1>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Data Loading
|
||||
### Leveraging Page Layouts
|
||||
|
||||
Astro pages can fetch data to help generate your pages. Astro provides two different tools to pages to help you do this: **fetch()** and **top-level await.**
|
||||
|
||||
📚 Read our [full guide](/en/guides/data-fetching) on data-fetching to learn more.
|
||||
To avoid repeating the same HTML elements on every page, you can move common `<head>` and `<body>` elements into your own [layout components](/en/core-components/layouts). You can use as many or as few layout components as you'd like.
|
||||
|
||||
```astro
|
||||
---
|
||||
// Example: Astro component scripts run at build time
|
||||
const response = await fetch('http://example.com/movies.json');
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
// Example: src/pages/index.astro
|
||||
import MySiteLayout from '../layouts/MySiteLayout.astro';
|
||||
---
|
||||
<!-- Output the result to the page -->
|
||||
<div>{JSON.stringify(data)}</div>
|
||||
<MySiteLayout>
|
||||
<p>My page content, wrapped in a layout!</p>
|
||||
</MySiteLayout>
|
||||
```
|
||||
|
||||
## Custom 404 Error Page
|
||||
📚 Read more about [layout components](/en/core-concepts/layouts) in Astro.
|
||||
|
||||
|
||||
## Markdown Pages
|
||||
|
||||
Astro also treats any Markdown (`.md`) files inside of `/src/pages/` as pages in your final website. These are commonly used for text-heavy pages like blog posts and documentation.
|
||||
|
||||
Page layouts are especially useful for [Markdown files.](#markdown-pages) Markdown files can use the special `layout` front matter property to specify a [layout component](/en/core-concepts/layout) that will wrap their Markdown content in a full `<html>...</html>` page document.
|
||||
|
||||
```md
|
||||
---
|
||||
# Example: src/pages/page.md
|
||||
layout: '../layouts/MySiteLayout.astro'
|
||||
title: 'My Markdown page'
|
||||
---
|
||||
# Title
|
||||
|
||||
This is my page, written in **Markdown.**
|
||||
```
|
||||
|
||||
📚 Read more about [Markdown](/en/guides/markdown-content) in Astro.
|
||||
|
||||
For a custom 404 error page create a `404.astro` file in `/src/pages`. That builds to a `404.html` page. Most [deploy services](/en/guides/deploy) will find and use it.
|
||||
This is special and different to the default behavior building `page.astro` (or `page/index.astro`) to `page/index.html`.
|
||||
|
||||
## Non-HTML Pages
|
||||
|
||||
> ⚠️ This feature is currently only supported with the `--experimental-static-build` CLI flag. This feature may be refined over the next few weeks/months as SSR support is finalized.
|
||||
|
||||
Non-HTML pages, like `.json` or `.xml`, can be built from `.js` and `.ts`. All that's needed is to export a `get()` function that returns a string `body` with the rendered file contents.
|
||||
Non-HTML pages, like `.json` or `.xml`, can be built from `.js` and `.ts`.
|
||||
|
||||
Built filenames and extensions are based on the source file's name, ex: `src/pages/data.json.ts` will be built to match the `/data.json` route in your final build.
|
||||
|
||||
```js
|
||||
// src/pages/company.json.ts
|
||||
export async function get() {
|
||||
return {
|
||||
body: JSON.stringify({
|
||||
name: 'Astro',
|
||||
url: 'https://astro.build/',
|
||||
}),
|
||||
};
|
||||
}
|
||||
```
|
||||
📚 Read more about generating [non-HTML pages](https://docs.astro.build/en/core-concepts/astro-pages/#non-html-pages) in Astro.
|
||||
|
||||
**Is this different from SSR?** Yes! This feature allows JSON, XML, etc. files to be output at build time. Keep an eye out for full SSR support if you need to build similar files when requested, for example as a serverless function in your deployment host.
|
||||
## Custom 404 Error Page
|
||||
|
||||
### Routing
|
||||
For a custom 404 error page, you can create a `404.astro` file in `/src/pages`.
|
||||
|
||||
File-based routing works the same as HTML pages, including dynamic routes with `getStaticPaths()`. See the [routing](/en/core-concepts/routing/) docs for more details.
|
||||
|
||||
### Data Loading
|
||||
|
||||
The [`Astro` global](/en/reference/api-reference/#astro-global) is only available in `.astro` files. Instead, [`import.meta.glob`](/en/reference/api-reference/#importmeta) can be used to load local `.md` files.
|
||||
|
||||
Similar to `.astro` pages, **fetch()** can be used to fetch data. 📚 Read our [full guide](/en/guides/data-fetching) on data-fetching to learn more.
|
||||
|
||||
### Examples
|
||||
|
||||
```typescript
|
||||
// src/pages/company.json.ts
|
||||
export async function get() {
|
||||
return {
|
||||
body: JSON.stringify({
|
||||
name: 'Astro Technology Company',
|
||||
url: 'https://astro.build/',
|
||||
}),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### Example with dynamic routes
|
||||
|
||||
What about `getStaticPaths()`? It **just works**™.
|
||||
|
||||
```typescript
|
||||
// src/pages/[slug].json.ts
|
||||
export async function getStaticPaths() {
|
||||
return [
|
||||
{ params: { slug: 'thing1' }},
|
||||
{ params: { slug: 'thing2' }}
|
||||
]
|
||||
}
|
||||
|
||||
export async function get(params) {
|
||||
const { slug } = params
|
||||
|
||||
return {
|
||||
body: // ...JSON.stringify()
|
||||
}
|
||||
}
|
||||
```
|
||||
This will build to a `404.html` page. Most [deploy services](/en/guides/deploy) will find and use it.
|
|
@ -4,152 +4,85 @@ title: Layouts
|
|||
description: An intro to layouts, a type of Astro component that is shared between pages for common layouts.
|
||||
---
|
||||
|
||||
**Layouts** are a special type of [Component](/en/core-concepts/astro-components) that help you share and reuse common page layouts within your project.
|
||||
**Layouts** are a special type of [Astro component](/en/core-concepts/astro-components) useful for creating reusable page templates.
|
||||
|
||||
Layouts are just like any other reusable Astro component. There’s no new syntax or APIs to learn. However, reusable page layouts are such a common pattern in web development that we created this guide to help you use them.
|
||||
A layout component is conventionally used to provide an [`.astro` or `.md` page](/en/core-concepts/astro-pages) both a **page shell** (`<html>`, `<head>` and `<body>` tags) and a `<slot>` to specify where in the layout page content should be injected.
|
||||
|
||||
## Usage
|
||||
Layouts often provide common `<head>` elements and common UI elements for the page such as headers, navigation bars and footers.
|
||||
|
||||
Astro layouts support props, slots, and all of the other features of Astro components. Layouts are just normal components, after all!
|
||||
Layout components are commonly placed in a `src/layouts` directory in your project.
|
||||
|
||||
Unlike other components, layouts will often contain the full page `<html>`, `<head>` and `<body>` (often referred to as the **page shell**).
|
||||
|
||||
It’s a common pattern to put all of your layout components in a single `src/layouts` directory.
|
||||
|
||||
## Example
|
||||
## Sample Layout
|
||||
|
||||
```astro
|
||||
---
|
||||
// src/layouts/BaseLayout.astro
|
||||
const {title} = Astro.props;
|
||||
// Example: src/layouts/MySiteLayout.astro
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
<title>Example Layout: {title}</title>
|
||||
<!-- ... -->
|
||||
</head>
|
||||
<body>
|
||||
<!-- Adds a navigation bar to every page. -->
|
||||
<nav>
|
||||
<a href="#">Home</a>
|
||||
<a href="#">Posts</a>
|
||||
<a href="#">Contact</a>
|
||||
</nav>
|
||||
<!-- slot: your page content will be injected here. -->
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
📚 The `<slot />` element lets Astro components define where any children elements (passed to the layout) should go. Learn more about how `<slot/>` works in our [Astro Component guide.](/en/core-concepts/astro-components)
|
||||
|
||||
Once you have your first layout, you can use it like you would any other component on your page. Remember that your layout contains your page `<html>`, `<head>`, and `<body>`. You only need to provide the custom page content.
|
||||
|
||||
```astro
|
||||
---
|
||||
// src/pages/index.astro
|
||||
import BaseLayout from '../layouts/BaseLayout.astro'
|
||||
---
|
||||
<BaseLayout title="Homepage">
|
||||
<h1>Hello, world!</h1>
|
||||
<p>This is my page content. It will be nested inside a layout.</p>
|
||||
</BaseLayout>
|
||||
```
|
||||
|
||||
## Nesting Layouts
|
||||
|
||||
You can nest layouts when you want to create more specific page types without copy-pasting. It is common in Astro to have one generic `BaseLayout` and then many more specific layouts (`PostLayout`, `ProductLayout`, etc.) that reuse and build on top of it.
|
||||
|
||||
```astro
|
||||
---
|
||||
// src/layouts/PostLayout.astro
|
||||
import BaseLayout from '../layouts/BaseLayout.astro'
|
||||
const {title, author} = Astro.props;
|
||||
---
|
||||
<!-- This layout reuses BaseLayout (see example above): -->
|
||||
<BaseLayout title={title}>
|
||||
<!-- Adds new post-specific content to every page. -->
|
||||
<div>Post author: {author}</div>
|
||||
<!-- slot: your page content will be injected here. -->
|
||||
<slot />
|
||||
</BaseLayout>
|
||||
```
|
||||
|
||||
## Composing Layouts
|
||||
|
||||
Sometimes, you need more granular control over your page. For instance, you may want to add SEO or social `meta` tags on some pages, but not others. You could implement this with a prop on your layout (`<BaseLayout addMeta={true} ...`) but at some point it may be easier to compose your layouts without nesting.
|
||||
|
||||
Instead of defining your entire `<html>` page as one big layout, you can define the `head` and `body` contents as smaller, separate components. This lets you compose multiple layouts together in unique ways on every page.
|
||||
|
||||
```astro
|
||||
---
|
||||
// src/layouts/BaseHead.astro
|
||||
const {title, description} = Astro.props;
|
||||
---
|
||||
<meta charset="UTF-8">
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description}>
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
|
||||
```
|
||||
|
||||
Notice how this layout doesn't include your page shell, and only includes some generic elements that should go in your `<head>`. This lets you combine multiple layout components together with more control over the overall page structure.
|
||||
|
||||
```astro
|
||||
---
|
||||
// src/pages/index.astro
|
||||
import BaseHead from '../layouts/BaseHead.astro';
|
||||
import OpenGraphMeta from '../layouts/OpenGraphMeta.astro';
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
<!-- Now, you have complete control over the head, per-page. -->
|
||||
<BaseHead title="Page Title" description="Page Description" />
|
||||
<OpenGraphMeta />
|
||||
<!-- You can even add custom, one-off elements as needed. -->
|
||||
<link rel="alternate" type="application/rss+xml" href="/feed/posts.xml">
|
||||
</head>
|
||||
<body>
|
||||
<!-- ... -->
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
The one downside to this approach is that you'll need to define the `<html>`, `<head>`, and `<body>` elements on every page yourself. This is needed to construct the page because the layout components no longer contain the full page shell.
|
||||
|
||||
## Markdown Layouts
|
||||
|
||||
Layouts are essential for Markdown files. Markdown files can declare a layout in the file frontmatter. Each Markdown file will be rendered to HTML and then injected into the layout’s `<slot />` location.
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Blog Post
|
||||
layout: ../layouts/PostLayout.astro
|
||||
---
|
||||
|
||||
This blog post will be **rendered** inside of the `<PostLayout />` layout.
|
||||
```
|
||||
|
||||
Markdown pages always pass a `content` prop to their layout, which is useful to grab information about the page, title, metadata, table of contents headers, and more.
|
||||
|
||||
```astro
|
||||
---
|
||||
// src/layouts/PostLayout.astro
|
||||
const { content } = Astro.props;
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
<title>{content.title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>{content.title}</h1>
|
||||
<h2>{content.description}</h2>
|
||||
<img src={content.image} alt="">
|
||||
<article>
|
||||
<!-- slot: Markdown content goes here! -->
|
||||
<slot />
|
||||
<slot /> <!-- your content is injected here -->
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
📚 Learn more about Astro’s markdown support in our [Markdown guide](/en/guides/markdown-content).
|
||||
```astro
|
||||
---
|
||||
// Example: src/pages/index.astro
|
||||
import MySiteLayout from '../layouts/MySiteLayout.astro';
|
||||
---
|
||||
<MySiteLayout>
|
||||
<p>My page content, wrapped in a layout!</p>
|
||||
</MySiteLayout>
|
||||
```
|
||||
|
||||
|
||||
📚 Learn more about how `<slot/>` works in our [Astro component guide.](/en/core-concepts/astro-components/#slots)
|
||||
|
||||
|
||||
## Nesting Layouts
|
||||
|
||||
Layout components do not need to contain an entire page worth of HTML. You can break your layouts into smaller components, and then reuse those components to create even more flexible, powerful layouts in your project.
|
||||
|
||||
For example, a common layout for blog posts may display a title, date and author. A `BlogPostLayout.astro` layout component could add this UI to the page and also leverage a larger, site-wide layout to handle the rest of your page.
|
||||
|
||||
```astro
|
||||
---
|
||||
// Example src/layout/BlogPostLayout.astro
|
||||
import BaseLayout from '../layouts/BaseLayout.astro'
|
||||
const {content} = Astro.props;
|
||||
---
|
||||
<BaseLayout>
|
||||
<h1>{content.title}</h1>
|
||||
<h2>Post author: {content.author}</h2>
|
||||
<slot />
|
||||
</BaseLayout>
|
||||
```
|
||||
|
||||
## Markdown Layouts
|
||||
|
||||
Page layouts are especially useful for [Markdown files.](#markdown-pages) Markdown files can use the special `layout` front matter property to specify a layout component that will wrap their Markdown content in a full page HTML document.
|
||||
|
||||
When a Markdown page uses a layout, it passes the layout a single `content` prop that includes all of the Markdown front matter data and final HTML output. See the `BlogPostLayout.astro` example above for an example of how you would use this `content` prop in your layout component.
|
||||
|
||||
|
||||
```markdown
|
||||
// src/pages/posts/post-1.md
|
||||
---
|
||||
title: Blog Post
|
||||
description: My first blog post!
|
||||
layout: ../layouts/BlogPostLayout.astro
|
||||
---
|
||||
This is a post written in Markdown.
|
||||
```
|
||||
|
||||
📚 Learn more about Astro’s Markdown support in our [Markdown guide](/en/guides/markdown-content).
|
|
@ -4,55 +4,102 @@ title: Project Structure
|
|||
description: Learn how to structure a project with Astro.
|
||||
---
|
||||
|
||||
Astro includes an opinionated folder layout for your project. Every Astro project must include these directories and files:
|
||||
Your new Astro project generated from the `create-astro` CLI wizard already includes some files and folders. Others, you will create yourself and add to Astro's existing file structure.
|
||||
|
||||
- `src/*` - Your project source code (components, pages, etc.)
|
||||
- `public/*` - Your non-code assets (fonts, icons, etc.)
|
||||
Here's how an Astro project is organized, and some files you will find in your new project.
|
||||
|
||||
## Directories and Files
|
||||
|
||||
Astro leverages an opinionated folder layout for your project. Every Astro project root should include the following directories and files:
|
||||
|
||||
- `src/*` - Your project source code (components, pages, styles, etc.)
|
||||
- `public/*` - Your non-code, unprocessed assets (fonts, icons, etc.)
|
||||
- `package.json` - A project manifest.
|
||||
- `astro.config.mjs` - An Astro configuration file. (optional)
|
||||
|
||||
The easiest way to set up your new project is with `npm init astro`. Check out our [Installation Guide](/en/installation) for a walkthrough of how to set up your project automatically (with `npm init astro`) or manually.
|
||||
### Example Project Tree
|
||||
|
||||
## Project Structure
|
||||
A common project directory might look like this:
|
||||
|
||||
```
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ ├── Header.astro
|
||||
│ │ └-─ Button.jsx
|
||||
│ ├── layouts/
|
||||
│ │ └-─ PostLayout.astro
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
│ │ ├── posts/
|
||||
│ │ │ ├── post1.md
|
||||
│ │ │ ├── post2.md
|
||||
│ │ │ └── post3.md
|
||||
│ │ └── index.astro
|
||||
│ └── styles/
|
||||
│ └-─ global.css
|
||||
├── public/
|
||||
│ ├── robots.txt
|
||||
│ ├── favicon.svg
|
||||
│ └-─ social-image.png
|
||||
├── astro.config.mjs
|
||||
└── package.json
|
||||
|
||||
```
|
||||
|
||||
### `src/`
|
||||
|
||||
The src folder is where most of your project source code lives. This includes:
|
||||
|
||||
- [Astro Components](/en/core-concepts/astro-components)
|
||||
- [Pages](/en/core-concepts/astro-pages)
|
||||
- [Layouts](/en/core-concepts/layouts)
|
||||
- [Frontend JS Components](/en/core-concepts/component-hydration)
|
||||
- [Styling (CSS, Sass)](/en/guides/styling)
|
||||
- [Astro components](/en/core-concepts/astro-components)
|
||||
- [Frontend components (React, etc.)](/en/core-concepts/component-hydration)
|
||||
- [Styles (CSS, Sass)](/en/guides/styling)
|
||||
- [Markdown](/en/guides/markdown-content)
|
||||
|
||||
Astro has complete control over how these files get processed, optimized, and bundled in your final site build. Some files (like Astro components) never make it to the browser directly and are instead rendered to HTML. Other files (like CSS) are sent to the browser but may be bundled with other CSS files depending on how your site uses them.
|
||||
Astro processes, optimizes, and bundles your `src/` files to create the final website that is shipped to the browser. Unlike the static `public/` directory, your `src/` files are built and handled for you by Astro.
|
||||
|
||||
Some files (like Astro components) are not even sent to the browser as written, but are instead rendered to static HTML. Other files (like CSS) are sent to the browser but may be optimized or bundled with other CSS files for performance.
|
||||
|
||||
### `src/components`
|
||||
|
||||
[Components](/en/core-concepts/astro-components) are reusable units of UI for your HTML pages. It is recommended (but not required) that you put your components in this directory. How you organize them within this directory is up to you.
|
||||
**Components** are reusable units of code for your HTML pages. These could be [Astro components](/en/core-concepts/astro-components), or [Frontend components](/en/core-concepts/component-hydration) like React or Vue. It is common to group and organize all of your project components together in this folder.
|
||||
|
||||
Your non-Astro UI components (React, Preact, Svelte, Vue, etc.) can also live in the `src/components` directory. Astro will automatically render all components to HTML unless you've enabled a frontend component via partial hydration.
|
||||
This is a common convention in Astro projects, but it is not required. Feel free to organize your components however you like!
|
||||
|
||||
### `src/layouts`
|
||||
|
||||
[Layouts](/en/core-concepts/layouts) are reusable components for HTML page layouts. It is recommended (but not required) that you put your layout components in this directory. How you organize them within this directory is up to you.
|
||||
[Layouts](/en/core-concepts/layouts) are special kind of component that wrap some content in a larger page layout. These are most often used by [Astro pages](/en/core-concepts/astro-pages) and [Markdown pages](/en/guides/markdown-content) to define the layout of the page.
|
||||
|
||||
Just like `src/components`, this directory is a common convention but not required.
|
||||
|
||||
### `src/pages`
|
||||
|
||||
[Pages](/en/core-concepts/astro-pages) contain all pages (`.astro` and `.md` supported) for your website. It is **required** that you put your pages in this directory.
|
||||
[Pages](/en/core-concepts/astro-pages) are special kind of component used to create new pages on your site. A page can be an Astro component, or a Markdown file that represents some page of content for your site.
|
||||
|
||||
> ⚠️ `src/pages` is a **required** sub-directory in your Astro project. Without it, your site will have no pages or routes!
|
||||
|
||||
### `src/styles`
|
||||
|
||||
It is a common convention to store your CSS or Sass files in a `src/styles` directory, but this is not required. As long as your styles live somewhere in the `src/` directory and are imported correctly, Astro will handle and optimize them.
|
||||
|
||||
### `public/`
|
||||
|
||||
For most users, the majority of your files will live inside of the `src/` directory so that Astro can properly handle and optimize them in your final build. By contrast, the `public/` directory is the place for any files to live outside of the Astro build process.
|
||||
The `public/` directory is for files and assets that do not need to be processed during Astro's build process. These files will be copied into the build folder untouched.
|
||||
|
||||
If you put a file into the public folder, it will not be processed by Astro. Instead it will be copied into the build folder untouched. This can be useful for assets like images and fonts, or when you need to include a specific file like `robots.txt` or `manifest.webmanifest`.
|
||||
This behavior makes `public/` ideal for common assets like images and fonts, or special files such as `robots.txt` and `manifest.webmanifest`.
|
||||
|
||||
You can place CSS and JavaScript in your `public/` directory, but be aware that those files will not be bundled or optimized in your final build.
|
||||
|
||||
💡 *As a general rule, any CSS or JavaScript that you write yourself should live in your `src/` directory.*
|
||||
|
||||
### `package.json`
|
||||
|
||||
This is a file used by JavaScript package managers to manage your dependencies. It also defines the scripts that are commonly used to run Astro (ex: `npm start`, `npm run build`).
|
||||
|
||||
For help creating a new `package.json` file for your project, check out the [manual setup](/en/guides/manual-setup) instructions.
|
||||
|
||||
### `astro.config.mjs`
|
||||
|
||||
This file is generated in every starter template and includes configuration options for your Astro project. Here you can specify renderers to use, devOptions, buildOptions, and more.
|
||||
|
||||
See the [Configuration Reference](https://docs.astro.build/en/reference/configuration-reference/#article) for details on setting configurations.
|
|
@ -26,7 +26,7 @@ You can add import aliases from either `tsconfig.json` or `jsconfig.json`.
|
|||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/components/*": ["src/components/*"]
|
||||
"@components/*": ["src/components/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,8 @@ With this change, you can now import using the aliases anywhere in your project:
|
|||
---
|
||||
// my-project/src/pages/about/company.astro
|
||||
|
||||
import Button from 'component:Button';
|
||||
import logoUrl from 'asset:logo.png';
|
||||
import Button from '@components/Button';
|
||||
import logoUrl from '@assets/logo.png';
|
||||
---
|
||||
```
|
||||
|
||||
|
|
|
@ -4,32 +4,64 @@ title: Using environment variables
|
|||
description: Learn how to use environment variables in an Astro project.
|
||||
---
|
||||
|
||||
Astro uses Vite for environment variables, and allows you to use any of its methods to get and set environment variables. Note that all environment variables must be prefixed with `PUBLIC_` to be accessible by client side code.
|
||||
Astro uses Vite for environment variables, and allows you to use any of its methods to get and set environment variables.
|
||||
|
||||
Note that while _all_ environment variables are available in sever-side code, only environment variables prefixed with `PUBLIC_` are avilable in client-side code.
|
||||
|
||||
See the official [Environment Variables example](https://github.com/withastro/astro/tree/main/examples/env-vars) for best practices.
|
||||
|
||||
For security purposes, only variables prefixed with `PUBLIC_` are accessible by client side code.
|
||||
|
||||
```ini
|
||||
SECRET_PASSWORD=password123
|
||||
PUBLIC_ANYBODY=there
|
||||
```
|
||||
|
||||
In this example, `PUBLIC_ANYBODY` will be available as `import.meta.env.PUBLIC_ANYBODY` in server or client code, while `SECRET_PASSWORD` will not.
|
||||
|
||||
> In prior releases, these variables were prefixed with `SNOWPACK_PUBLIC_` and required the `@snowpack/plugin-env` plugin.
|
||||
|
||||
The ability to access private variables on the server side is [still being discussed](https://github.com/withastro/astro/issues/1765).
|
||||
|
||||
## Setting environment variables
|
||||
|
||||
Vite includes `dotenv` by default, allowing you to easily set environment variables without any extra configuration in Astro projects. You can also attach a mode (either `production` or `development`) to the filename, like `.env.production` or `.env.development`, which makes the environment variables only take effect in that mode.
|
||||
In Astro v0.21+, environment variables can be loaded from `.env` files in your project directory.
|
||||
|
||||
You can also attach a mode (either `production` or `development`) to the filename, like `.env.production` or `.env.development`, which makes the environment variables only take effect in that mode.
|
||||
|
||||
Just create a `.env` file in the project directory and add some variables to it.
|
||||
|
||||
```bash
|
||||
# .env
|
||||
# This will only be available when run on the server!
|
||||
DB_PASSWORD="foobar"
|
||||
# This will be available everywhere!
|
||||
PUBLIC_POKEAPI="https://pokeapi.co/api/v2"
|
||||
```
|
||||
|
||||
```ini
|
||||
.env # loaded in all cases
|
||||
.env.local # loaded in all cases, ignored by git
|
||||
.env.[mode] # only loaded in specified mode
|
||||
.env.[mode].local # only loaded in specified mode, ignored by git
|
||||
```
|
||||
|
||||
## Getting environment variables
|
||||
|
||||
Instead of using `process.env`, with Vite you use `import.meta.env`, which uses the `import.meta` feature added in ES2020 (don't worry about browser support though, Vite replaces all `import.meta.env` mentions with static values). For example, to get the `PUBLIC_POKEAPI` environment variable, you could use `import.meta.env.PUBLIC_POKEAPI`.
|
||||
|
||||
```js
|
||||
fetch(`${import.meta.env.PUBLIC_POKEAPI}/pokemon/squirtle`);
|
||||
// When import.meta.env.SSR === true
|
||||
const data = await db(import.meta.env.DB_PASSWORD);
|
||||
|
||||
// When import.meta.env.SSR === false
|
||||
const data = fetch(`${import.meta.env.PUBLIC_POKEAPI}/pokemon/squirtle`);
|
||||
```
|
||||
|
||||
> ⚠️WARNING⚠️:
|
||||
> Because Vite statically replaces `import.meta.env`, you cannot access it with dynamic keys like `import.meta.env[key]`.
|
||||
|
||||
|
||||
|
||||
## IntelliSense for TypeScript
|
||||
|
||||
By default, Vite provides type definition for `import.meta.env` in `vite/client.d.ts`. While you can define more custom env variables in `.env.[mode]` files, you may want to get TypeScript IntelliSense for user-defined env variables which prefixed with `PUBLIC_`.
|
||||
|
@ -38,6 +70,7 @@ To achieve, you can create an `env.d.ts` in `src` directory, then augment `Impor
|
|||
|
||||
```ts
|
||||
interface ImportMetaEnv {
|
||||
readonly DB_PASSWORD: string;
|
||||
readonly PUBLIC_POKEAPI: string;
|
||||
// more env variables...
|
||||
}
|
||||
|
|
102
smoke/docs-main/src/pages/en/guides/manual-setup.md
Normal file
|
@ -0,0 +1,102 @@
|
|||
---
|
||||
layout: ~/layouts/MainLayout.astro
|
||||
title: Manual Setup
|
||||
description: How to install and set up Astro manually
|
||||
---
|
||||
If you do not wish to use a [starter template](https://github.com/withastro/astro/tree/main/examples), you can install Astro dependencies manually and create a new project with a `package.json` file and an Astro `index` page.
|
||||
|
||||
## 1. Create your directory
|
||||
|
||||
Create an empty directory with the name of your project, and then navigate into it.
|
||||
|
||||
```bash
|
||||
mkdir my-astro-project
|
||||
cd my-astro-project
|
||||
```
|
||||
|
||||
Once you are in your new directory, create your project `package.json` file. This is how you will manage your project dependencies, including Astro. If you aren't familiar with this file format, run the following command to create one.
|
||||
|
||||
```bash
|
||||
npm init --yes
|
||||
```
|
||||
|
||||
|
||||
## 2. Install Astro
|
||||
|
||||
First, install the Astro project dependencies inside your project.
|
||||
|
||||
```bash
|
||||
npm install astro
|
||||
```
|
||||
|
||||
Then, replace any placeholder "scripts" section of your `package.json` with the following:
|
||||
|
||||
```diff
|
||||
"scripts": \{
|
||||
- "test": "echo \"Error: no test specified\" && exit 1"
|
||||
+ "dev": "astro dev",
|
||||
+ "build": "astro build",
|
||||
+ "preview": "astro preview"
|
||||
},
|
||||
```
|
||||
|
||||
You'll use these scripts later in the guide to start Astro and run its different commands.
|
||||
## 3. Create your first page
|
||||
|
||||
In your text editor, create a new file in your directory at `src/pages/index.astro`. This will be your first Astro page in the project.
|
||||
|
||||
For this guide, copy-and-paste the following code snippet (including `---` dashes) into your new file:
|
||||
|
||||
```astro
|
||||
---
|
||||
// Welcome to Astro! Everything between these "---" code fences
|
||||
// is your "component front matter". It never runs in the browser.
|
||||
console.log('This runs in your terminal, not the browser!');
|
||||
---
|
||||
<!-- Below is your "component template." It's just HTML, but with
|
||||
some magic sprinkled in to help you build great templates. -->
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello, World!</h1>
|
||||
</body>
|
||||
</html>
|
||||
<style>
|
||||
h1 {
|
||||
color: orange;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## 4. Create your first static asset
|
||||
|
||||
You will also want to create a `public/` directory to store your static assets. Astro will always include these assets in your final build, so you can safely reference them from inside your component templates.
|
||||
|
||||
In your text editor, create a new file in your directory at `public/robots.txt`. `robots.txt` is a simple file that most sites will include to tell search bots like Google how to treat your site.
|
||||
|
||||
For this guide, copy-and-paste the following code snippet into your new file:
|
||||
|
||||
```
|
||||
# Example: Allow all bots to scan and index your site.
|
||||
# Full syntax: https://developers.google.com/search/docs/advanced/robots/create-robots-txt
|
||||
User-agent: *
|
||||
Allow: /
|
||||
```
|
||||
|
||||
## 5. Next steps
|
||||
|
||||
If you have followed the steps above, your project directory should now look like this:
|
||||
|
||||
```
|
||||
- src/
|
||||
- pages/
|
||||
- index.astro
|
||||
- public/
|
||||
- robots.txt
|
||||
- package.json
|
||||
- package-lock.json (or: yarn.lock, pnpm-lock.json, etc.)
|
||||
- node_modules/
|
||||
```
|
||||
|
||||
Congratulations, you're now set up to use Astro!
|
||||
|
||||
If you followed this guide completely, you can jump directly to [Step 3: Start](/en/installation#3-start-) to continue and learn how to run Astro for the first time.
|
|
@ -190,18 +190,23 @@ Using images or videos follows Astro’s normal import rules:
|
|||
|
||||
### Components
|
||||
|
||||
You can import any component into your markdown file and use it along the markdown syntax.
|
||||
You can import components from any framework into your markdown file and use it along the markdown syntax. Front matter variables are available to your components from the `frontmatter` object.
|
||||
|
||||
```markdown
|
||||
---
|
||||
layout: ../layouts/BaseLayout.astro
|
||||
setup: |
|
||||
import Author from '../../components/Author.astro'
|
||||
import Button from '../../components/Button.svelte'
|
||||
import MyReactComponent from '../components/MyReactComponent.jsx'
|
||||
author: Leon
|
||||
---
|
||||
# Blog post title
|
||||
# Hydrating on Visibility
|
||||
|
||||
<MyReactComponent client:visible >
|
||||
# Hello world!
|
||||
</MyReactComponent>
|
||||
|
||||
<Author name={frontmatter.author}/>
|
||||
<Button>Label</Button>
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -122,6 +122,28 @@ It’s recommended to only use this in scenarios where a `<link>` tag won’t wo
|
|||
|
||||
📚 Read our full guide on [Astro component syntax][astro-component] to learn more about using the `<style>` tag.
|
||||
|
||||
### Variables in Scripts & Styles
|
||||
|
||||
In Astro v0.21+, _serializable_ server-side variables can be passed into client-side `<style>` or `<script>`.
|
||||
|
||||
```astro
|
||||
---
|
||||
// tick.astro
|
||||
const foregroundColor = "rgb(221 243 228)";
|
||||
const backgroundColor = "rgb(24 121 78)";
|
||||
---
|
||||
<style define:vars={{ foregroundColor, backgroundColor }}>
|
||||
h-tick {
|
||||
background-color: var(--backgroundColor);
|
||||
border-radius: 50%;
|
||||
color: var(--foregroundColor);
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
}
|
||||
</style>
|
||||
<h-tick>✓</h-tick>
|
||||
```
|
||||
|
||||
## Autoprefixer
|
||||
|
||||
[Autoprefixer][autoprefixer] takes care of cross-browser CSS compatibility for you. Use it in astro by installing it (`npm install --save-dev autoprefixer`) and adding a `postcss.config.cjs` file to the root of your project:
|
||||
|
@ -129,7 +151,9 @@ It’s recommended to only use this in scenarios where a `<link>` tag won’t wo
|
|||
```js
|
||||
// postcss.config.cjs
|
||||
module.exports = {
|
||||
plugins: [require('autoprefixer')],
|
||||
plugins: {
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -200,10 +224,11 @@ _Note: CSS inside `public/` will **not** be transformed! Place it within `src/`
|
|||
|
||||
### 🍃 Tailwind
|
||||
|
||||
Astro can be configured to use [Tailwind][tailwind] easily! Install the dependencies:
|
||||
Astro can be configured to use [Tailwind][tailwind] easily! Install the dependencies, and ensure you have PostCSS installed. (This second step was optional in previous releases, but is required now):
|
||||
|
||||
```
|
||||
npm install --save-dev tailwindcss
|
||||
npm install --save-dev postcss
|
||||
```
|
||||
|
||||
And create 2 files in your project root: `tailwind.config.cjs` and `postcss.config.cjs`:
|
||||
|
@ -222,7 +247,9 @@ module.exports = {
|
|||
```js
|
||||
// postcss.config.cjs
|
||||
module.exports = {
|
||||
plugins: [require('tailwindcss')],
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
|
|
|
@ -3,174 +3,120 @@ layout: ~/layouts/MainLayout.astro
|
|||
title: Installation
|
||||
description: How to install Astro with NPM, PNPM, or Yarn.
|
||||
---
|
||||
Use npm, pnpm or yarn to create and set up a new Astro project locally!
|
||||
|
||||
There are a few different ways to install Astro in a new project.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Node.js** - `14.15.0`, `v16.0.0`, or higher.
|
||||
- **Text editor** - We recommend [VS Code](https://code.visualstudio.com/) with our [Official Astro extension](https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode).
|
||||
- **Terminal** - Astro is mainly accessed via the terminal’s command-line.
|
||||
- **Terminal** - Astro is accessed through its command-line interface (CLI).
|
||||
|
||||
For demonstration purposes, we will be using [`npm`](https://www.npmjs.com/) in the examples below, but you could also use [`yarn`](https://yarnpkg.com/) or [`pnpm`](https://pnpm.io/) if you prefer an npm alternative.
|
||||
## 1. Create your project
|
||||
|
||||
## Create Astro
|
||||
|
||||
`npm init astro` is the easiest way to install Astro in a new project. Run this command in your terminal to start our `create-astro` install wizard to assist you with setting up a new project.
|
||||
Run one of the following commands in your terminal to start our handy install wizard, `create-astro`. This will walk you through creating your very first Astro project in whatever directory you run it in.
|
||||
|
||||
```shell
|
||||
# With NPM
|
||||
# npm
|
||||
npm init astro
|
||||
|
||||
# Yarn
|
||||
# yarn
|
||||
yarn create astro
|
||||
|
||||
# Pnpm
|
||||
# pnpm
|
||||
pnpm create astro
|
||||
```
|
||||
|
||||
[`create-astro`](https://github.com/withastro/astro/tree/main/packages/create-astro) wizard lets you choose from a set of [starter templates](https://github.com/withastro/astro/tree/main/examples) or alternatively, you could import your own Astro project directly from GitHub.
|
||||
> ⚔️ Prefer to go it alone? Read our [manual setup](/en/guides/manual-setup) instructions instead.
|
||||
|
||||
```bash
|
||||
# Note: Replace "my-astro-project" with the name of your project.
|
||||
|
||||
# npm 6.x
|
||||
npm init astro my-astro-project --template starter
|
||||
# npm 7+ (extra double-dash is needed)
|
||||
npm init astro my-astro-project -- --template starter
|
||||
If `create-astro` starts successfully, you will see a short list of starter templates to choose from:
|
||||
- `starter`: A great starter template for anyone wanting to explore Astro.
|
||||
- `minimal`: A template that just includes the bare minimium to get started.
|
||||
- `blog, portfolio, docs, etc`: opinionated themes for specific use-cases.
|
||||
|
||||
If you choose the `starter` template, you will also be asked to select which [additional frameworks](/en/core-concepts/component-hydration) (React, Svelte, Vue, Solid, Preact), if any, you would like to include in your project. (Additional frameworks can also be added manually later.)
|
||||
|
||||
> 💡 Or, you can install any of our [many starter templates](https://github.com/withastro/astro/tree/main/examples) directly via the command line:
|
||||
```shell
|
||||
# npm
|
||||
npm init astro -- --template framework-svelte
|
||||
|
||||
# yarn
|
||||
yarn create astro my-astro-project --template starter
|
||||
yarn create astro -- --template with-nanostores
|
||||
|
||||
# pnpm
|
||||
pnpm create astro my-astro-project -- --template starter
|
||||
# Using a third-party template
|
||||
npm init astro my-astro-project -- --template [GITHUB_USER]/[REPO_NAME]
|
||||
# Using a third-party template, inside a repo
|
||||
npm init astro my-astro-project -- --template [GITHUB_USER]/[REPO_NAME]/path/to/template
|
||||
pnpm create astro -- --template with-tailwindcss
|
||||
```
|
||||
|
||||
After `create-astro` scaffolds out your project, remember to install your projects dependencies using npm or your package manager of choice. In this example, we'll use npm:
|
||||
## 2. Install
|
||||
|
||||
When the `create-astro` install wizard is complete, you should see some recommended instructions on your screen to follow that will help you complete setup and start your new project.
|
||||
|
||||
The only required step remaining is to install your project's dependencies using a package manager like npm:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm install
|
||||
|
||||
# yarn
|
||||
yarn
|
||||
|
||||
#pnmp
|
||||
pnmp install
|
||||
|
||||
```
|
||||
|
||||
You can now [Start](#start-astro) your Astro project. Once you have completed assembling your Astro project you can then [Build](#build-astro) your project. Astro would then package up your application and have the static files ready for you to [Deploy](/en/guides/deploy) to your favourite hosting provider.
|
||||
This is also a great chance to run `git init` in your new directory, if you plan to use the tool [Git](https://git-scm.com/) in your project.
|
||||
|
||||
## Manual Install
|
||||
## 3. Start ✨
|
||||
|
||||
You can also set up Astro without the aide of the `create-astro` wizard, below are the few extra steps that are required to get Astro going.
|
||||
You can expect to use Astro's built-in dev server for most of your project development. This is how you will run your project locally during development.
|
||||
|
||||
### Set up your project
|
||||
To start, use your package manager to run your pre-configured start script:
|
||||
|
||||
```bash
|
||||
# Make and enter a new directory
|
||||
mkdir my-astro-project
|
||||
cd my-astro-project
|
||||
# npm
|
||||
npm start
|
||||
|
||||
#yarn
|
||||
yarn start
|
||||
|
||||
#pnpm
|
||||
pnpm run start
|
||||
```
|
||||
|
||||
Create an empty directory with the name of your project, and then navigate into it:
|
||||
If all goes well, Astro should now be serving your project on [http://localhost:3000](http://localhost:3000)!
|
||||
|
||||
### Create `package.json`
|
||||
|
||||
```bash
|
||||
# This command will create a basic package.json for you
|
||||
npm init --yes
|
||||
```
|
||||
|
||||
Astro is designed to work with the entirety of the npm package ecosystem. This is managed by a project manifest at the root of your project known as `package.json` . If you're not familiar with the `package.json` file, we highly recommend you to have a quick read over it on [the npm documentation](https://docs.npmjs.com/creating-a-package-json-file).
|
||||
|
||||
### Install Astro
|
||||
|
||||
Following the instructions above, you should have a directory with a single `package.json` file inside of it. You can now set up Astro inside your project.
|
||||
|
||||
```bash
|
||||
npm install astro
|
||||
```
|
||||
|
||||
You can now replace the placeholder "scripts" section of your `package.json` file that `npm init` created for you with the following:
|
||||
|
||||
```diff
|
||||
"scripts": {
|
||||
- "test": "echo \"Error: no test specified\" && exit 1"
|
||||
+ "dev": "astro dev",
|
||||
+ "build": "astro build",
|
||||
+ "preview": "astro preview"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The [`dev`](#start-astro) command launches the Astro Dev Server on `http://localhost:3000`. Once your project is ready, the [`build`](#build-astro) command outputs your project to the `dist/` directory. [Read more about deploying Astro in the Deploy guide.](/en/guides/deploy)
|
||||
|
||||
### Create your first page
|
||||
|
||||
Astro Open up your favourite text editor, and create a new file in your project:
|
||||
|
||||
1. Create a new file at `src/pages/index.astro`
|
||||
2. Copy-and-paste the following snippet (including `---` dashes) into it.
|
||||
|
||||
```astro
|
||||
---
|
||||
// JS/TS Code written in between the (---) code fence,
|
||||
// is ran solely on the Server!
|
||||
console.log('See me in the Terminal')
|
||||
---
|
||||
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello, World!</h1>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style lang='css||scss'>
|
||||
body{
|
||||
h1{
|
||||
color:orange;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// JS Code entered here is ran entirely on the Browser
|
||||
console.log('See me in the devTools')
|
||||
</script>
|
||||
```
|
||||
|
||||
Above is an example of the Astro’s Component’s Syntax, which comprises of both HTML & JSX.
|
||||
|
||||
You can create more pages in the `src/pages` directory, and Astro will use the filename to create new pages on your site. For example, by creating a new file at `src/pages/about.astro` (reusing the previous snippet), Astro will generate a new page at the URL : `http://localhost/about`
|
||||
|
||||
## [Start Astro](#start-astro)
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Astro will now start serving your application on `http://localhost:3000`. By opening this URL in your browser, you should see the Astro’s “Hello, World”.
|
||||
|
||||
If you need to share your development progress on the local network or check out the app from a phone, just add the following option to `astro.config.mjs`:
|
||||
|
||||
```js
|
||||
devOptions: {
|
||||
hostname: '0.0.0.0',
|
||||
}
|
||||
```
|
||||
|
||||
## [Build Astro](#build-astro)
|
||||
Astro will listen for live file changes in your `src/` directory, so you will not need to restart the server as you make changes during development.
|
||||
|
||||
If you aren't able to open your project in the browser, go back to the terminal where you ran the `start` command to see what went wrong.
|
||||
|
||||
## 4. Deploy to the web
|
||||
|
||||
It's time to deploy your project to the web! Run the `build` command in your project to build your static website to a new `dist/` folder in your project.
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run build
|
||||
|
||||
#yarn
|
||||
yarn build
|
||||
|
||||
#pnpm
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
This will instruct Astro to build your site and save it directly to disk. Your application is now ready in the `dist/` directory.
|
||||
When the command finishes, you should have a new `dist/` folder in your project that you can deploy directly to your favorite web host.
|
||||
|
||||
To get started hosting your website for free, check out our proud hosting partner, [Netlify](https://www.netlify.com/). For instructions on deploying to whatever host you choose, read our detailed [deployment guide](/en/guides/deploy).
|
||||
|
||||
## Next Steps
|
||||
|
||||
Success! You're now ready to start developing!
|
||||
|
||||
We highly encourage you to get more familiar with the way Astro works. You can do so by further exploring our Docs, we suggest that you consider the following:
|
||||
Success! Now you're ready to start developing!
|
||||
|
||||
📚 Learn more about Astro’s project structure in our [Project Structure guide.](/en/core-concepts/project-structure)
|
||||
|
||||
📚 Learn more about Astro’s component syntax in our [Astro Components guide.](/en/core-concepts/astro-components)
|
||||
|
||||
📚 Learn more about Astro’s file-based routing in our [Routing guide.](/en/core-concepts/astro-pages)
|
||||
📚 Learn more about Astro’s file-based routing in our [Routing guide.](/en/core-concepts/astro-pages)
|
57
smoke/docs-main/src/pages/en/integrations/integrations.md
Normal file
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
layout: ~/layouts/MainLayout.astro
|
||||
title: Integrations
|
||||
---
|
||||
|
||||
Members of the Astro community have been successfully integrating several third-party services into their Astro websites!
|
||||
|
||||
Here are some production sites, repositories, blog posts and videos from the community demonstrating how you can connect Astro with a variety of popular CMS, eCommerce, Authentication/Authorization, Search and Comment technologies.
|
||||
|
||||
## Production Sites
|
||||
|
||||
[Replicant Band](https://replicant.band) - Astro / GraphCMS / Snipcart / Tailwind
|
||||
|
||||
[Spread Bagelry](https://spreadbagelry.com) - Astro / Vue / Tailwind / Strapi CMS / Cloudinary
|
||||
|
||||
[Public Transport Forum New Zealand](https://publictransportforum.nz/articles) - Astro / Netlify CMS
|
||||
|
||||
[My Workshops Live](https://myworkshops.live) - Astro / Svelte / Firebase / Vonage / Web Speech API / reveal.js
|
||||
|
||||
[Rafid Muhymin Wafi](https://softhardsystem.com/) - Astro / Tailwind / WordPress: Headless CMS, comments, search
|
||||
|
||||
[meizuflux](https://meizuflux.com) - Astro / GraphCMS
|
||||
|
||||
[Sarah Rainsberger](https://www.rainsberger.ca/) - Astro / GitHub Giscus (Comments)
|
||||
|
||||
|
||||
[Astro Docs](https://github.com/withastro/docs) - Our own docs use Algolia search in Astro!
|
||||
|
||||
|
||||
## Blog Posts / Videos
|
||||
|
||||
[NavillusBlog](https://navillus.dev/blog/astro-plus-snipcart) - **Post**: Astro + Snipcart repository and demo site
|
||||
|
||||
[Cassidy Williams](https://www.netlify.com/blog/2021/07/23/build-a-modern-shopping-site-with-astro-and-serverless-functions/) - **Post**: Building Shopify Stores with Astro and the Storefront API
|
||||
|
||||
[Learn With Jason](https://youtube.com/watch?v=FJOJmKFngLI) - **Video**: Building a custom cart in Astro with Shopify Storefront API
|
||||
|
||||
[Chris Bongers](https://blog.openreplay.com/building-an-astro-website-with-wordpress-as-a-headless-cms) - **Post**: Building an Astro Website with WordPress as a Headless CMS
|
||||
|
||||
[Front End Horse](https://www.youtube.com/watch?v=qFUfuDSLdxM) - **Video**: Building with Astro & Prismic
|
||||
|
||||
[Jaydan Urwin](https://www.youtube.com/watch?v=-jAWLTfsSQw) - **Video**: Create your own Blog with Astro and Sanity.io
|
||||
|
||||
[Aftab Alam](https://aalam.vercel.app/blog/astro-and-git-cms-netlify) - **Post**: Author your Astro site's content with Git-based CMSs
|
||||
|
||||
[Chris Bongers](https://aviyel.com/post/1006/adding-typesense-search-to-an-astro-static-generated-website) - **Post**: Adding Typesense Search to an Astro Website
|
||||
|
||||
## Repositories / Starter Templates
|
||||
|
||||
[delucis/astro-netlify-cms](https://github.com/delucis/astro-netlify-cms/) - Astro Starter Template with Netlify CMS
|
||||
|
||||
[PhilDL/astro-starter-ghost](https://github.com/PhilDL/astro-starter-ghost) - A starter template for a static blog using Ghost CMS and Astro
|
||||
|
||||
[p13rnd/centauri](https://github.com/p13rnd/centauri) - Astro template: Tailwind, Svelte and authentication with Supabase
|
||||
|
||||
|
||||
> See examples of even more starter repositories and sites built with Astro at [Awesome Astro](https://github.com/one-aalam/awesome-astro#%E2%84%B9%EF%B8%8F-repositoriesstarter-kitscomponents)
|
|
@ -4,8 +4,132 @@ title: Migration Guide
|
|||
description: How to migrate your project to latest version of Astro.
|
||||
---
|
||||
|
||||
Until Astro reaches v1.0, we expect to make some breaking changes across minor versions (ex: `v0.1 -> v0.2`). This guide exists to help you migrate to the latest versions of Astro and keep your codebase up-to-date.
|
||||
## Planned Deprecations
|
||||
|
||||
Astro is currently testing its next build engine behind an opt-in flag: `--experimental-static-build`. You can learn more about this project by reading our blog post [Scaling Astro to 10,000+ Pages.](https://astro.build/blog/experimental-static-build/)
|
||||
|
||||
In a future version of Astro, this will become the default build behavior. To prepare for the transition, be aware of the following changes that will be required to move to this new build engine. You can make these changes to your codebase at any time so that you are ready ahead of schedule.
|
||||
|
||||
### Deprecated: Astro.resolve()
|
||||
|
||||
`Astro.resolve()` allows you to get resolved URLs to assets that you might want to reference in the browser. This was most commonly used inside of `<link>` and `<img>` tags to load CSS files and images as needed. Unfortunately, this will no longer work in future versions of Astro. Instead, you'll want to upgrade your asset references to one of the following future-proof options available going forward:
|
||||
|
||||
#### How to Resolve CSS Files
|
||||
|
||||
**1. ESM Import (Recommended)**
|
||||
|
||||
**Example:** `import './style.css';`
|
||||
**When to use this:** If your CSS file lives inside of the `src/` directory, and you want automatic CSS build and optimization features.
|
||||
|
||||
Use an ESM import to add some CSS onto the page. Astro detects these CSS imports and then builds, optimizes, and adds the CSS to the page automatically. This is the easiest way to migrate from `Astro.resolve()` while keeping the automatic building/bundling that Astro provides.
|
||||
|
||||
```astro
|
||||
---
|
||||
// Example: Astro will include and optimize this CSS for you automatically
|
||||
import './style.css';
|
||||
---
|
||||
<html><!-- Your page here --></html>
|
||||
```
|
||||
|
||||
Importing CSS files should work anywhere that ESM imports are supported, including:
|
||||
- JavaScript files
|
||||
- TypeScript files
|
||||
- Astro component front matter
|
||||
- non-Astro components like React, Svelte, and others
|
||||
|
||||
When a CSS file is imported using this method, any `@import` statements are also resolved and inlined into the imported CSS file. All `url()` references are also resolved relative to the source file, and any `url()` referenced assets will be included in the final build.
|
||||
|
||||
|
||||
**2. Absolute URL Path**
|
||||
|
||||
**Example:** `<link href="/style.css">`
|
||||
**When to use this:** If your CSS file lives inside of `public/`, and you prefer to create your HTML `link` element yourself.
|
||||
|
||||
You can references any file inside of the `public/` directory by absolute URL path in your component template. This is a good option if you want to control the `<link>` tag on the page yourself. However, this approach also skips the CSS processing, bundling and optimizations that are provided by Astro when you use the `import` method described above.
|
||||
|
||||
We recommend using the `import` approach over the abolute URL approach, since it provides the best possible CSS performance and features by default.
|
||||
|
||||
#### How to Resolve JavaScript Files
|
||||
|
||||
|
||||
**1. Absolute URL Path**
|
||||
|
||||
**Example:** `<script src="/some-external-script.js" />`
|
||||
**When to use this:** If your JavaScript file lives inside of `public/`.
|
||||
|
||||
You can references any file inside of the `public/` directory by absolute URL path in your Astro component templates. This is a good default option for external scripts, because it lets you control the `<script >` tag on the page yourself.
|
||||
|
||||
Note that this approach skips the JavaScript processing, bundling and optimizations that are provided by Astro when you use the `import` method described below. However, this may be preferred for any external scripts that have already been published and minified seperately from Astro. If your script was downloaded from an external source, then this method is probably preferred.
|
||||
|
||||
**2. ESM Import via `<script hoist>`**
|
||||
|
||||
**Example:** `<script hoist>import './some-external-script.js';</script>`
|
||||
**When to use this:** If your external script lives inside of `src/` _and_ it supports the ESM module type.
|
||||
|
||||
Use an ESM import inside of a `<script hoist>` element in your Astro template, and Astro will include the JavaScript file in your final build. Astro detects these JavaScript client-side imports and then builds, optimizes, and adds the CSS to the page automatically. This is the easiest way to migrate from `Astro.resolve()` while keeping the automatic building/bundling that Astro provides.
|
||||
|
||||
```astro
|
||||
<script hoist>
|
||||
import './some-external-script.js';
|
||||
</script>
|
||||
```
|
||||
|
||||
Note that Astro will bundle this external script with the rest of your client-side JavaScript, and load it in the `type="module"` script context. Some older JavaScript files may not be written for the `module` context, in which case they may need to be updated to use this method.
|
||||
|
||||
#### How to Resolve Images & Other Assets
|
||||
|
||||
**1. Absolute URL Path (Recommended)**
|
||||
|
||||
**Example:** `<img src="/penguin.png">`
|
||||
**When to use this:** If your asset lives inside of `public/`.
|
||||
|
||||
If you place your images inside of `public/` you can safely reference them by absolute URL path directly in your component templates. This is the simplest way to reference an asset that you can use today, and it is recommended for most users who are getting started with Astro.
|
||||
|
||||
**2. ESM Import**
|
||||
|
||||
**Example:** `import imgUrl from './penguin.png'`
|
||||
**When to use this:** If your asset lives inside of the `src/` directory, and you want automatic optimization features like filename hashing.
|
||||
|
||||
This works inside of any JavaScript or Astro component, and returns a resolved URL to the final image. Once you have the resolved URL, you can use it anywhere inside of the component template.
|
||||
|
||||
```astro
|
||||
---
|
||||
// Example: Astro will include this image file in your final build
|
||||
import imgUrl from './penguin.png';
|
||||
---
|
||||
<img src={imgUrl} />
|
||||
```
|
||||
|
||||
Similar to how Astro handles CSS, the ESM import allows Astro to perform some simple build optimizations for you automatically. For example, any asset inside of `src/` that is imported using an ESM import (ex: `import imgUrl from './penguin.png'`) will have its filename hashed automatically. This can let you cache the file more aggressively on the server, improving user performance. In the future, Astro may add more optimizations like this.
|
||||
|
||||
**Tip:** If you dislike static ESM imports, Astro also supports dynamic ESM imports. We only recommend this option if you prefer this syntax: `<img src={(await import('./penguin.png')).default} />`.
|
||||
|
||||
### Deprecated: `<script>` Default Processing
|
||||
|
||||
Previously, all `<script>` elements were read from the final HTML output and processed + bundled automatically. This behavior is no longer the default. Starting in `--experimental-static-build`, you must opt-in to `<script>` element processing via the `hoist` attribute:
|
||||
|
||||
```astro
|
||||
<script>
|
||||
// Will be rendered into the HTML exactly as written!
|
||||
// ESM imports will not be resolved relative to the file.
|
||||
</script>
|
||||
<script hoist>
|
||||
// Processed! Bundled! ESM imports work, even to npm packages.
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
## Migrate to v0.23
|
||||
|
||||
### Missing Sass Error
|
||||
|
||||
```
|
||||
Preprocessor dependency "sass" not found. Did you install it?
|
||||
```
|
||||
|
||||
In our quest to reduce npm install size, we've moved [Sass](https://sass-lang.com/) out to an optional dependency. If you use Sass in your project, you'll want to make sure that you run `npm install sass --save-dev` to save it as a dependency.
|
||||
|
||||
### Deprecated: Unescaped HTML
|
||||
|
||||
In Astro v0.23+, unescaped HTML content in expressions is now deprecated.
|
||||
|
@ -185,11 +309,11 @@ Ensure you have PostCSS installed. This was optional in previous releases, but i
|
|||
|
||||
#### Imports on top
|
||||
|
||||
In Astro v0.21+, a bug has been introduced that requires imports inside components to be at the top of your frontmatter.
|
||||
In Astro v0.21+, a bug has been introduced that requires imports inside components to be at the top of your front matter.
|
||||
|
||||
```astro
|
||||
---
|
||||
import Component from '../components/component.astro'
|
||||
import Component from '../components/Component.astro'
|
||||
const whereShouldIPutMyImports = "on top!"
|
||||
---
|
||||
```
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
---
|
||||
layout: ~/layouts/MainLayout.astro
|
||||
title: Quick Start
|
||||
description: The easiest way to get started quickly with Astro.
|
||||
---
|
||||
|
||||
```shell
|
||||
# prerequisite: check that Node.js is 14.15.0+, or 16+
|
||||
node --version
|
||||
|
||||
# Make a new project directory, and navigate directly into it
|
||||
mkdir my-astro-project && cd $_
|
||||
|
||||
# prepare for liftoff...
|
||||
npm init astro
|
||||
|
||||
# install dependencies
|
||||
npm install
|
||||
|
||||
# start developing!
|
||||
npm run dev
|
||||
```
|
||||
|
||||
For production sites,
|
||||
|
||||
```shell
|
||||
# when you're ready: build your static site to `dist/`
|
||||
npm run build
|
||||
```
|
||||
|
||||
To learn more about installing and using Astro for the first time, please [read our installation guide.](/en/installation)
|
||||
|
||||
If you prefer to learn by example, check out our [complete library of examples](https://github.com/withastro/astro/tree/main/examples) on GitHub. You can check out any of these examples locally by running `npm init astro -- --template "EXAMPLE_NAME"`.
|
||||
|
||||
## Start your project
|
||||
|
||||
From inside your project directory, enter the following command into your terminal:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Astro will now start serving your application on [http://localhost:3000](http://localhost:3000). Opening this URL in your browser, you should see the Astro’s "Hello, World".
|
||||
|
||||
The server will listen for live file changes in your `src/` directory, so you do not need to restart the application as you make changes during development.
|
||||
|
||||
## Build your project
|
||||
|
||||
To build your project, from inside your directory enter the following build command into your terminal:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
This will instruct Astro to build your site and save it directly to disk. Your application is now ready in the `dist/` directory.
|
||||
|
||||
## Deploy your project
|
||||
|
||||
Astro sites are static, so they can be deployed to your favourite host:
|
||||
|
||||
- [AWS S3 bucket](https://aws.amazon.com/s3/)
|
||||
- [Google Firebase](https://firebase.google.com/)
|
||||
- [Netlify](https://www.netlify.com/)
|
||||
- [Vercel](https://vercel.com/)
|
||||
- [Read more about deploying Astro in our Deploy guide.](/en/guides/deploy)
|
||||
|
||||
## Next Steps
|
||||
|
||||
Success! You're now ready to start developing!
|
||||
|
||||
We recommend that you to take some time to get more familiar with the way Astro works. You can do so by further exploring our Docs, we suggest that you consider the following:
|
||||
|
||||
📚 Learn more about Astro’s project structure in our [Project Structure guide.](/en/core-concepts/project-structure)
|
||||
|
||||
📚 Learn more about Astro’s component syntax in our [Astro Components guide.](/en/core-concepts/astro-components)
|
||||
|
||||
📚 Learn more about Astro’s file-based routing in our [Routing guide.](/en/core-concepts/astro-pages)
|
|
@ -55,7 +55,7 @@ See the [list of languages supported by Prism](https://prismjs.com/#supported-la
|
|||
|
||||
```astro
|
||||
---
|
||||
import Debug from 'astro/debug';
|
||||
import { Debug } from 'astro/components';
|
||||
const serverObject = {
|
||||
a: 0,
|
||||
b: "string",
|
||||
|
|
124
yarn.lock
|
@ -156,7 +156,7 @@
|
|||
jsonpointer "^5.0.0"
|
||||
leven "^3.1.0"
|
||||
|
||||
"@astrojs/compiler@^0.11.0", "@astrojs/compiler@^0.11.4":
|
||||
"@astrojs/compiler@^0.11.4":
|
||||
version "0.11.4"
|
||||
resolved "https://registry.yarnpkg.com/@astrojs/compiler/-/compiler-0.11.4.tgz#933853cf37ba2cbf0213a88463fd48c3a4329a07"
|
||||
integrity sha512-T598FTCgBFjjPLPClvn+lc2SFGAJkjaF+lbxvHNjzmUpOYdz7YyH1apd3XAZvDp5r5WBBhicB6693GhQRpf3oQ==
|
||||
|
@ -181,33 +181,6 @@
|
|||
vscode-languageserver-types "^3.16.0"
|
||||
vscode-uri "^3.0.2"
|
||||
|
||||
"@astrojs/renderer-react@0.5.0-next.0":
|
||||
version "0.5.0-next.0"
|
||||
resolved "https://registry.yarnpkg.com/@astrojs/renderer-react/-/renderer-react-0.5.0-next.0.tgz#452990c3298f540c5e5650ef5745ec96433bc016"
|
||||
integrity sha512-1DuaWllhddOvTmLS9ZOcMchQ/6HBhMlngiN4mXlkRH8y0RixBeg6aLWPEj3N46ZI4Zh73JOPUSWeGuVrDKVmHg==
|
||||
dependencies:
|
||||
"@babel/plugin-transform-react-jsx" "^7.16.7"
|
||||
react "^17.0.2"
|
||||
react-dom "^17.0.2"
|
||||
|
||||
"@astrojs/renderer-svelte@0.4.0-next.0":
|
||||
version "0.4.0-next.0"
|
||||
resolved "https://registry.yarnpkg.com/@astrojs/renderer-svelte/-/renderer-svelte-0.4.0-next.0.tgz#2de092b6d7d9125a62da82ad63fba16413b24994"
|
||||
integrity sha512-5DwL3Tt+vSKdLzUe6A7rbqG6KvrRIGzF8YU2k5F/rYPI6XOAZ1vlCD3SPY5sZwu0/qjH12BG+AwG82wlNJIenA==
|
||||
dependencies:
|
||||
"@sveltejs/vite-plugin-svelte" "^1.0.0-next.37"
|
||||
postcss-load-config "^3.1.1"
|
||||
svelte "^3.46.4"
|
||||
svelte-preprocess "^4.10.2"
|
||||
|
||||
"@astrojs/renderer-vue@0.4.0-next.0":
|
||||
version "0.4.0-next.0"
|
||||
resolved "https://registry.yarnpkg.com/@astrojs/renderer-vue/-/renderer-vue-0.4.0-next.0.tgz#5adc55870c84fceea90cb1b16ebacadc8968e60a"
|
||||
integrity sha512-GJOH84SStDBNST1jwt1TT7aQ8z5aZ3K6w5tci0XFPq16BnT+KyHNbZITFTkY0nszF3evswV/Z0c0FJxlHeUeXQ==
|
||||
dependencies:
|
||||
"@vitejs/plugin-vue" "^2.2.0"
|
||||
vue "^3.2.30"
|
||||
|
||||
"@astropub/webapi@^0.10.1", "@astropub/webapi@^0.10.13":
|
||||
version "0.10.14"
|
||||
resolved "https://registry.yarnpkg.com/@astropub/webapi/-/webapi-0.10.14.tgz#f3e118718d1353170ec9ea0adc4a725796717a77"
|
||||
|
@ -1745,6 +1718,20 @@
|
|||
magic-string "^0.25.7"
|
||||
svelte-hmr "^0.14.9"
|
||||
|
||||
"@tailwindcss/aspect-ratio@^0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.0.tgz#c635dd7331cbcc1b111cebdc2647dd3493ebdd3e"
|
||||
integrity sha512-WJu0I4PpqNPuutpaA9zDUq2JXR+lorZ7PbLcKNLmb6GL9/HLfC7w3CRsMhJF4BbYd/lkY6CfXOvkYpuGnZfkpQ==
|
||||
|
||||
"@tailwindcss/typography@^0.5.2":
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.2.tgz#24b069dab24d7a2467d01aca0dd432cb4b29f0ee"
|
||||
integrity sha512-coq8DBABRPFcVhVIk6IbKyyHUt7YTEC/C992tatFB+yEx5WGBQrCgsSFjxHUr8AWXphWckadVJbominEduYBqw==
|
||||
dependencies:
|
||||
lodash.castarray "^4.4.0"
|
||||
lodash.isplainobject "^4.0.6"
|
||||
lodash.merge "^4.6.2"
|
||||
|
||||
"@tootallnate/once@1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||
|
@ -2602,64 +2589,6 @@ astro-icon@^0.6.0:
|
|||
resolve-pkg "^2.0.0"
|
||||
svgo "^2.8.0"
|
||||
|
||||
astro@0.23.0-next.10:
|
||||
version "0.23.0-next.10"
|
||||
resolved "https://registry.yarnpkg.com/astro/-/astro-0.23.0-next.10.tgz#fbacb8d9fb18399caa44726a4cb64761835d448e"
|
||||
integrity sha512-WKALrpi92aEdc48zi2cfgc2T24l7maVurfZ75Ugl2C805Y6MXwnKfe50Wk1s50u5gEoz9LLqFqCqU6EESW2x2g==
|
||||
dependencies:
|
||||
"@astrojs/compiler" "^0.11.0"
|
||||
"@astrojs/language-server" "^0.8.6"
|
||||
"@astrojs/markdown-remark" "^0.6.1-next.2"
|
||||
"@astrojs/prism" "0.4.0"
|
||||
"@astrojs/renderer-preact" "^0.5.0-next.0"
|
||||
"@astrojs/renderer-react" "0.5.0-next.0"
|
||||
"@astrojs/renderer-svelte" "0.4.0-next.0"
|
||||
"@astrojs/renderer-vue" "0.4.0-next.0"
|
||||
"@astropub/webapi" "^0.10.1"
|
||||
"@babel/core" "^7.15.8"
|
||||
"@babel/traverse" "^7.15.4"
|
||||
"@proload/core" "^0.2.2"
|
||||
"@proload/plugin-tsm" "^0.1.0"
|
||||
"@types/babel__core" "^7.1.15"
|
||||
"@types/debug" "^4.1.7"
|
||||
"@web/parse5-utils" "^1.3.0"
|
||||
ci-info "^3.2.0"
|
||||
common-ancestor-path "^1.0.1"
|
||||
eol "^0.9.1"
|
||||
es-module-lexer "^0.9.3"
|
||||
esbuild "0.13.7"
|
||||
estree-walker "^3.0.0"
|
||||
fast-glob "^3.2.7"
|
||||
fast-xml-parser "^4.0.0-beta.3"
|
||||
html-entities "^2.3.2"
|
||||
htmlparser2 "^7.1.2"
|
||||
kleur "^4.1.4"
|
||||
magic-string "^0.25.7"
|
||||
mime "^3.0.0"
|
||||
morphdom "^2.6.1"
|
||||
parse5 "^6.0.1"
|
||||
path-to-regexp "^6.2.0"
|
||||
postcss "^8.3.8"
|
||||
prismjs "^1.25.0"
|
||||
rehype-slug "^5.0.0"
|
||||
resolve "^1.20.0"
|
||||
rollup "^2.64.0"
|
||||
semver "^7.3.5"
|
||||
send "^0.17.1"
|
||||
serialize-javascript "^6.0.0"
|
||||
shiki "^0.10.0"
|
||||
shorthash "^0.0.2"
|
||||
slash "^4.0.0"
|
||||
sourcemap-codec "^1.4.8"
|
||||
srcset-parse "^1.1.0"
|
||||
string-width "^5.0.0"
|
||||
strip-ansi "^7.0.1"
|
||||
supports-esm "^1.0.0"
|
||||
tsconfig-resolver "^3.0.1"
|
||||
vite "^2.8.0"
|
||||
yargs-parser "^21.0.0"
|
||||
zod "^3.8.1"
|
||||
|
||||
async@0.9.x:
|
||||
version "0.9.2"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
|
||||
|
@ -2677,7 +2606,7 @@ at-least-node@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
|
||||
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
|
||||
|
||||
autoprefixer@^10.4.0:
|
||||
autoprefixer@^10.4.0, autoprefixer@^10.4.2:
|
||||
version "10.4.2"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b"
|
||||
integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==
|
||||
|
@ -5874,6 +5803,11 @@ locate-path@^6.0.0:
|
|||
dependencies:
|
||||
p-locate "^5.0.0"
|
||||
|
||||
lodash.castarray@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115"
|
||||
integrity sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=
|
||||
|
||||
lodash.clonedeep@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
|
||||
|
@ -5884,6 +5818,11 @@ lodash.debounce@^4.0.8:
|
|||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
|
||||
|
||||
lodash.isplainobject@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
||||
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
|
||||
|
||||
lodash.merge@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
|
@ -6642,11 +6581,6 @@ mocha@^9.1.3:
|
|||
yargs-parser "20.2.4"
|
||||
yargs-unparser "2.0.0"
|
||||
|
||||
morphdom@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/morphdom/-/morphdom-2.6.1.tgz#e868e24f989fa3183004b159aed643e628b4306e"
|
||||
integrity sha512-Y8YRbAEP3eKykroIBWrjcfMw7mmwJfjhqdpSvoqinu8Y702nAwikpXcNFDiIkyvfCLxLM9Wu95RZqo4a9jFBaA==
|
||||
|
||||
mri@^1.1.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
|
||||
|
@ -7334,7 +7268,7 @@ postcss-value-parser@^4.2.0:
|
|||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8.1.10, postcss@^8.3.8, postcss@^8.4.6:
|
||||
postcss@^8.1.10, postcss@^8.3.8, postcss@^8.4.6, postcss@^8.4.7:
|
||||
version "8.4.7"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.7.tgz#f99862069ec4541de386bf57f5660a6c7a0875a8"
|
||||
integrity sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==
|
||||
|
@ -7774,7 +7708,7 @@ regjsparser@^0.8.2:
|
|||
dependencies:
|
||||
jsesc "~0.5.0"
|
||||
|
||||
rehype-autolink-headings@^6.1.0:
|
||||
rehype-autolink-headings@^6.1.0, rehype-autolink-headings@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/rehype-autolink-headings/-/rehype-autolink-headings-6.1.1.tgz#0cb874a56f3de6ead1c2268d7f0fc5006f244db5"
|
||||
integrity sha512-NMYzZIsHM3sA14nC5rAFuUPIOfg+DFmf9EY1YMhaNlB7+3kK/ZlE6kqPfuxr1tsJ1XWkTrMtMoyHosU70d35mA==
|
||||
|
@ -8765,7 +8699,7 @@ svgo@^2.8.0:
|
|||
picocolors "^1.0.0"
|
||||
stable "^0.1.8"
|
||||
|
||||
tailwindcss@^3.0.5:
|
||||
tailwindcss@^3.0.23, tailwindcss@^3.0.5:
|
||||
version "3.0.23"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.23.tgz#c620521d53a289650872a66adfcb4129d2200d10"
|
||||
integrity sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==
|
||||
|
|