Merge branch 'docs-sync-1'
This commit is contained in:
commit
9c7921300c
50 changed files with 1587 additions and 1547 deletions
18
docs-www/.gitignore
vendored
18
docs-www/.gitignore
vendored
|
@ -1,18 +0,0 @@
|
|||
# build output
|
||||
dist
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
.snowpack/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
|
@ -1,5 +0,0 @@
|
|||
export default {
|
||||
renderers: [
|
||||
'@astrojs/renderer-preact'
|
||||
]
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "docs-www",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "astro dev",
|
||||
"build": "astro build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"astro": "^0.15.1"
|
||||
},
|
||||
"snowpack": {
|
||||
"workspaceRoot": ".."
|
||||
}
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
.language-css > code,
|
||||
.language-sass > code,
|
||||
.language-scss > code {
|
||||
color: #fd9170;
|
||||
}
|
||||
|
||||
[class*="language-"] .namespace {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.token.atrule {
|
||||
color: #c792ea;
|
||||
}
|
||||
|
||||
.token.attr-name {
|
||||
color: #ffcb6b;
|
||||
}
|
||||
|
||||
.token.attr-value {
|
||||
color: #a5e844;
|
||||
}
|
||||
|
||||
.token.attribute {
|
||||
color: #a5e844;
|
||||
}
|
||||
|
||||
.token.boolean {
|
||||
color: #c792ea;
|
||||
}
|
||||
|
||||
.token.builtin {
|
||||
color: #ffcb6b;
|
||||
}
|
||||
|
||||
.token.cdata {
|
||||
color: #80cbc4;
|
||||
}
|
||||
|
||||
.token.char {
|
||||
color: #80cbc4;
|
||||
}
|
||||
|
||||
.token.class {
|
||||
color: #ffcb6b;
|
||||
}
|
||||
|
||||
.token.class-name {
|
||||
color: #f2ff00;
|
||||
}
|
||||
|
||||
.token.comment {
|
||||
color: #616161;
|
||||
}
|
||||
|
||||
.token.constant {
|
||||
color: #c792ea;
|
||||
}
|
||||
|
||||
.token.deleted {
|
||||
color: #ff6666;
|
||||
}
|
||||
|
||||
.token.doctype {
|
||||
color: #616161;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
color: #ff6666;
|
||||
}
|
||||
|
||||
.token.function {
|
||||
color: #c792ea;
|
||||
}
|
||||
|
||||
.token.hexcode {
|
||||
color: #f2ff00;
|
||||
}
|
||||
|
||||
.token.id {
|
||||
color: #c792ea;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.important {
|
||||
color: #c792ea;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.inserted {
|
||||
color: #80cbc4;
|
||||
}
|
||||
|
||||
.token.keyword {
|
||||
color: #c792ea;
|
||||
}
|
||||
|
||||
.token.number {
|
||||
color: #fd9170;
|
||||
}
|
||||
|
||||
.token.operator {
|
||||
color: #89ddff;
|
||||
}
|
||||
|
||||
.token.prolog {
|
||||
color: #616161;
|
||||
}
|
||||
|
||||
.token.property {
|
||||
color: #80cbc4;
|
||||
}
|
||||
|
||||
.token.pseudo-class {
|
||||
color: #a5e844;
|
||||
}
|
||||
|
||||
.token.pseudo-element {
|
||||
color: #a5e844;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #89ddff;
|
||||
}
|
||||
|
||||
.token.regex {
|
||||
color: #f2ff00;
|
||||
}
|
||||
|
||||
.token.selector {
|
||||
color: #ff6666;
|
||||
}
|
||||
|
||||
.token.string {
|
||||
color: #a5e844;
|
||||
}
|
||||
|
||||
.token.symbol {
|
||||
color: #c792ea;
|
||||
}
|
||||
|
||||
.token.tag {
|
||||
color: #ff6666;
|
||||
}
|
||||
|
||||
.token.unit {
|
||||
color: #fd9170;
|
||||
}
|
||||
|
||||
.token.url {
|
||||
color: #ff6666;
|
||||
}
|
||||
|
||||
.token.variable {
|
||||
color: #ff6666;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<svg width="256" height="256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
#flame { fill: #FF5D01; }
|
||||
#a { fill: #000014; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#a { fill: #fff; }
|
||||
}
|
||||
</style>
|
||||
<path id="a" fill-rule="evenodd" clip-rule="evenodd" d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z" />
|
||||
<path id="flame" fill-rule="evenodd" clip-rule="evenodd" d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z" />
|
||||
</svg>
|
Before Width: | Height: | Size: 1.2 KiB |
|
@ -1,350 +0,0 @@
|
|||
@import './theme';
|
||||
@import './code';
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:root {
|
||||
--user-font-scale: 1rem - 16px;
|
||||
--max-width: calc(100% - 2rem);
|
||||
}
|
||||
|
||||
@media (min-width: 50em) {
|
||||
:root {
|
||||
--max-width: 48em;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
font-family: var(--font-body);
|
||||
font-size: 1rem;
|
||||
font-size: clamp(0.875rem, 0.4626rem + 1.0309vw + var(--user-font-scale), 1.125rem);
|
||||
line-height: 1.625;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.content main > * + * {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
:is(h1, h2, h3, h4, h5, h6) {
|
||||
margin-bottom: 1.38rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
:is(h1, h2) {
|
||||
max-width: 40ch;
|
||||
}
|
||||
|
||||
:is(h2, h3):not(:first-child) {
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: clamp(2.488rem, 1.9240rem + 1.4100vw, 3.052rem);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: clamp(2.074rem, 1.7070rem + 0.9175vw, 2.441rem);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: clamp(1.728rem, 1.5030rem + 0.5625vw, 1.953rem);
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: clamp(1.44rem, 1.3170rem + 0.3075vw, 1.563rem);
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: clamp(1.2rem, 1.1500rem + 0.1250vw, 1.25rem);
|
||||
}
|
||||
|
||||
p {
|
||||
color: var(--theme-text-light);
|
||||
}
|
||||
|
||||
small, .text_small {
|
||||
font-size: 0.833rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--theme-accent);
|
||||
font-weight: 400;
|
||||
text-underline-offset: 0.08em;
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
a > code:not([class*="language"]) {
|
||||
position: relative;
|
||||
color: var(--theme-accent);
|
||||
background: transparent;
|
||||
text-underline-offset: var(--padding-block);
|
||||
}
|
||||
|
||||
a > code:not([class*="language"])::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
background: var(--theme-accent);
|
||||
opacity: var(--theme-accent-opacity);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:focus {
|
||||
outline: 2px solid currentColor;
|
||||
outline-offset: 0.25em;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 600;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Supporting Content */
|
||||
|
||||
code:not([class*="language"]) {
|
||||
--border-radius: 3px;
|
||||
--padding-block: 0.2rem;
|
||||
--padding-inline: 0.33rem;
|
||||
|
||||
font-family: var(--font-mono);
|
||||
font-size: .85em;
|
||||
color: inherit;
|
||||
background-color: var(--theme-code-inline-bg);
|
||||
padding: var(--padding-block) var(--padding-inline);
|
||||
margin: calc(var(--padding-block) * -1) -0.125em;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
pre > code:not([class*="language"]) {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
pre {
|
||||
position: relative;
|
||||
background-color: var(--theme-code-bg);
|
||||
color: var(--theme-code-text);
|
||||
--padding-block: 1rem;
|
||||
--padding-inline: 2rem;
|
||||
padding: var(--padding-block) var(--padding-inline);
|
||||
padding-right: calc(var(--padding-inline) * 2);
|
||||
margin-left: calc(50vw - var(--padding-inline));
|
||||
transform: translateX(-50vw);
|
||||
|
||||
line-height: 1.414;
|
||||
width: calc(100vw + 4px);
|
||||
max-width: calc(100% + (var(--padding-inline) * 2));
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 37.75em) {
|
||||
pre {
|
||||
--padding-inline: 1.25rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 2rem 0;
|
||||
padding: 0.5em 1rem;
|
||||
border-left: 3px solid rgba(0, 0, 0, 0.35);
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 0 0.25rem 0.25rem 0;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
header button {
|
||||
background-color: var(--theme-bg);
|
||||
}
|
||||
header button:hover,
|
||||
header button:focus {
|
||||
background: var(--theme-text);
|
||||
color: var(--theme-bg);
|
||||
}
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
gap: 0.25em;
|
||||
padding: 0.33em 0.67em;
|
||||
border: 0;
|
||||
background: var(--theme-bg);
|
||||
display: flex;
|
||||
font-size: 1rem;
|
||||
align-items: center;
|
||||
gap: 0.25em;
|
||||
border-radius: 99em;
|
||||
background-color: var(--theme-bg);
|
||||
}
|
||||
button:hover {
|
||||
|
||||
}
|
||||
|
||||
#theme-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25em;
|
||||
padding: 0.33em 0.67em;
|
||||
margin-left: -0.67em;
|
||||
margin-right: -0.67em;
|
||||
border-radius: 99em;
|
||||
background-color: var(--theme-bg);
|
||||
}
|
||||
#theme-toggle:focus-within {
|
||||
outline: 2px solid transparent;
|
||||
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
|
||||
}
|
||||
|
||||
#theme-toggle > label {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.5rem;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
opacity: 0.5;
|
||||
transition: transform 120ms ease-out, opacity 120ms ease-out;
|
||||
}
|
||||
|
||||
#theme-toggle > label:hover,
|
||||
#theme-toggle > label:focus {
|
||||
transform: scale(1.125);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#theme-toggle .checked {
|
||||
color: var(--theme-accent);
|
||||
transform: scale(1.125);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input[name="theme-toggle"] {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
nav h4 {
|
||||
font-weight: 400;
|
||||
font-size: 1.25rem;
|
||||
margin: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.edit-on-github,
|
||||
.header-link {
|
||||
font-size: 1rem;
|
||||
padding-left: 1rem;
|
||||
border-left: 4px solid var(--theme-divider);
|
||||
}
|
||||
|
||||
.edit-on-github:hover,
|
||||
.edit-on-github:focus,
|
||||
.header-link:hover,
|
||||
.header-link:focus {
|
||||
color: var(--theme-text-light);
|
||||
border-left-color: var(--theme-text-lighter);
|
||||
}
|
||||
|
||||
.header-link:focus-within {
|
||||
color: var(--theme-text-light);
|
||||
border-left-color: var(--theme-text-lighter);
|
||||
}
|
||||
|
||||
.header-link.active {
|
||||
border-left-color: var(--theme-accent);
|
||||
color: var(--theme-accent);
|
||||
}
|
||||
|
||||
.header-link.depth-2 {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.header-link.depth-3 {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
.header-link.depth-4 {
|
||||
padding-left: 3rem;
|
||||
}
|
||||
|
||||
.edit-on-github,
|
||||
.header-link a {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.edit-on-github {
|
||||
margin-top: 2rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
.edit-on-github > * {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
font-size: 1rem;
|
||||
margin-bottom: 0;
|
||||
transform: translateX(0);
|
||||
transition: 120ms transform ease-out;
|
||||
}
|
||||
|
||||
.nav-link:hover,
|
||||
.nav-link:focus {
|
||||
color: var(--theme-text-lighter);
|
||||
transform: translateX(0.25em);
|
||||
}
|
||||
|
||||
.nav-link:focus-within {
|
||||
color: var(--theme-text-lighter);
|
||||
transform: translateX(0.25em);
|
||||
}
|
||||
|
||||
.nav-link a {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav-groups > li + li {
|
||||
margin-top: 2rem;
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
:root {
|
||||
--font-fallback: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;
|
||||
--font-body: system-ui, var(--font-fallback);
|
||||
--font-mono: source-code-pro,Menlo,Monaco,Consolas,'Courier New',monospace;
|
||||
|
||||
--color-white: #FFF;
|
||||
--color-black: #000014;
|
||||
|
||||
--color-gray-50: #F9FAFB;
|
||||
--color-gray-100: #F3F4F6;
|
||||
--color-gray-200: #E5E7EB;
|
||||
--color-gray-300: #D1D5DB;
|
||||
--color-gray-400: #9CA3AF;
|
||||
--color-gray-500: #6B7280;
|
||||
--color-gray-600: #4B5563;
|
||||
--color-gray-700: #374151;
|
||||
--color-gray-800: #1F2937;
|
||||
--color-gray-900: #111827;
|
||||
|
||||
--color-blue: #3894FF;
|
||||
--color-blue-rgb: 56,148,255;
|
||||
--color-green: #17C083;
|
||||
--color-green-rgb: 23,192,131;
|
||||
--color-orange: #FF5D01;
|
||||
--color-orange-rgb: 255,93,1;
|
||||
--color-purple: #882DE7;
|
||||
--color-purple-rgb: 136,45,231;
|
||||
--color-red: #FF1639;
|
||||
--color-red-rgb: 255,22,57;
|
||||
--color-yellow: #FFBE2D;
|
||||
--color-yellow-rgb: 255,190,45;
|
||||
}
|
||||
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--theme-accent: var(--color-blue);
|
||||
--theme-accent-rgb: var(--color-blue-rgb);
|
||||
--theme-accent-opacity: 0.1;
|
||||
--theme-divider: var(--color-gray-100);
|
||||
--theme-text: var(--color-gray-800);
|
||||
--theme-text-light: var(--color-gray-600);
|
||||
--theme-text-lighter: var(--color-gray-400);
|
||||
--theme-bg: var(--color-white);
|
||||
--theme-bg-offset: var(--color-gray-100);
|
||||
--theme-bg-accent: rgba(var(--theme-accent-rgb), var(--theme-accent-opacity));
|
||||
--theme-code-inline-bg: var(--color-gray-100);
|
||||
--theme-code-text: var(--color-gray-100);
|
||||
--theme-code-bg: var(--color-gray-700);
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--theme-bg);
|
||||
color: var(--theme-text);
|
||||
}
|
||||
|
||||
:root.theme-dark {
|
||||
color-scheme: dark;
|
||||
--theme-accent-opacity: 0.3;
|
||||
--theme-divider: var(--color-gray-900);
|
||||
--theme-text: var(--color-gray-200);
|
||||
--theme-text-light: var(--color-gray-400);
|
||||
--theme-text-lighter: var(--color-gray-600);
|
||||
--theme-bg: var(--color-black);
|
||||
--theme-bg-offset: var(--color-gray-900);
|
||||
--theme-code-inline-bg: var(--color-gray-800);
|
||||
--theme-code-text: var(--color-gray-200);
|
||||
--theme-code-bg: var(--color-gray-900);
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: var(--theme-accent);
|
||||
background-color: rgba(var(--theme-accent-rgb), var(--theme-accent-opacity));
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
(() => {
|
||||
const root = document.documentElement;
|
||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
root.classList.add('theme-dark');
|
||||
} else {
|
||||
root.classList.remove('theme-dark');
|
||||
}
|
||||
})();
|
|
@ -1,15 +0,0 @@
|
|||
---
|
||||
import AvatarList from './AvatarList.astro';
|
||||
---
|
||||
|
||||
<footer>
|
||||
<AvatarList />
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
footer {
|
||||
margin-top: auto;
|
||||
padding: 2rem 0;
|
||||
border-top: 3px solid var(--theme-divider);
|
||||
}
|
||||
</style>
|
|
@ -1,74 +0,0 @@
|
|||
<!-- Thanks to @5t3ph for https://smolcss.dev/#smol-avatar-list! -->
|
||||
|
||||
<ul class="avatar-list">
|
||||
<li><a href="https://smolcss.dev/#smol-avatar-list"><img alt="Avatar 1" width="64" height="64" src='https://avataaars.io/?avatarStyle=Transparent&topType=LongHairBun&accessoriesType=Blank&hairColor=Auburn&facialHairType=BeardMedium&facialHairColor=Auburn&clotheType=ShirtCrewNeck&clotheColor=Blue01&eyeType=Side&eyebrowType=RaisedExcitedNatural&mouthType=Serious&skinColor=Tanned' /></a></li>
|
||||
<li><a href="https://smolcss.dev/#smol-avatar-list"><img alt="Avatar 2" width="64" height="64" src='https://avataaars.io/?avatarStyle=Transparent&topType=LongHairDreads&accessoriesType=Blank&hairColor=Brown&facialHairType=Blank&clotheType=ShirtScoopNeck&clotheColor=PastelGreen&eyeType=Default&eyebrowType=DefaultNatural&mouthType=Smile&skinColor=Tanned' /></a></li>
|
||||
<li><a href="https://smolcss.dev/#smol-avatar-list"><img alt="Avatar 3" width="64" height="64" src='https://avataaars.io/?avatarStyle=Transparent&topType=LongHairCurly&hairColor=BrownDark&facialHairType=Blank&clotheType=GraphicShirt&clotheColor=Pink&graphicType=Diamond&eyeType=Side&eyebrowType=Default&mouthType=Default&skinColor=Brown'/></a></li>
|
||||
</ul>
|
||||
|
||||
<style>
|
||||
.avatar-list {
|
||||
--avatar-size: 2.5rem;
|
||||
--avatar-count: 3;
|
||||
|
||||
display: grid;
|
||||
list-style: none;
|
||||
/* Default to displaying most of the avatar to
|
||||
enable easier access on touch devices, ensuring
|
||||
the WCAG touch target size is met or exceeded */
|
||||
grid-template-columns: repeat(
|
||||
var(--avatar-count),
|
||||
max(44px, calc(var(--avatar-size) / 1.15))
|
||||
);
|
||||
/* `padding` matches added visual dimensions of
|
||||
the `box-shadow` to help create a more accurate
|
||||
computed component size */
|
||||
padding: 0.08em;
|
||||
font-size: var(--avatar-size);
|
||||
}
|
||||
|
||||
@media (any-hover: hover) and (any-pointer: fine) {
|
||||
.avatar-list {
|
||||
/* We create 1 extra cell to enable the computed
|
||||
width to match the final visual width */
|
||||
grid-template-columns: repeat(
|
||||
calc(var(--avatar-count) + 1),
|
||||
calc(var(--avatar-size) / 1.75)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-list li {
|
||||
width: var(--avatar-size);
|
||||
height: var(--avatar-size);
|
||||
}
|
||||
|
||||
.avatar-list li:hover ~ li a,
|
||||
.avatar-list li:focus-within ~ li a {
|
||||
transform: translateX(33%);
|
||||
}
|
||||
|
||||
.avatar-list img,
|
||||
.avatar-list a {
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.avatar-list a {
|
||||
transition: transform 180ms ease-in-out;
|
||||
}
|
||||
|
||||
.avatar-list img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.avatar-list a:focus {
|
||||
outline: 2px solid transparent;
|
||||
/* Double-layer trick to work for dark and light backgrounds */
|
||||
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
|
||||
}
|
||||
</style>
|
|
@ -1,61 +0,0 @@
|
|||
import type { FunctionalComponent } from 'preact';
|
||||
import { h } from 'preact';
|
||||
import { useState, useEffect, useRef } from 'preact/hooks';
|
||||
import EditOnGithub from './EditOnGithub';
|
||||
|
||||
const DocSidebar: FunctionalComponent<{ headers: any[]; editHref: string }> = ({ headers = [], editHref }) => {
|
||||
const itemOffsets = useRef([]);
|
||||
const [activeId, setActiveId] = useState<string>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const getItemOffsets = () => {
|
||||
const titles = document.querySelectorAll('article :is(h2, h3, h4)');
|
||||
itemOffsets.current = Array.from(titles).map((title) => ({
|
||||
id: title.id,
|
||||
topOffset: title.getBoundingClientRect().top + window.scrollY,
|
||||
}));
|
||||
};
|
||||
|
||||
const onScroll = () => {
|
||||
const itemIndex = itemOffsets.current.findIndex((item) => item.topOffset > window.scrollY + window.innerHeight / 3);
|
||||
if (itemIndex === 0) {
|
||||
setActiveId(undefined);
|
||||
} else if (itemIndex === -1) {
|
||||
setActiveId(itemOffsets.current[itemOffsets.current.length - 1].id);
|
||||
} else {
|
||||
setActiveId(itemOffsets.current[itemIndex - 1].id);
|
||||
}
|
||||
};
|
||||
|
||||
getItemOffsets();
|
||||
window.addEventListener('resize', getItemOffsets);
|
||||
window.addEventListener('scroll', onScroll);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', getItemOffsets);
|
||||
window.removeEventListener('scroll', onScroll);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<nav>
|
||||
<div>
|
||||
<h4>Contents</h4>
|
||||
<ul>
|
||||
{headers
|
||||
.filter(({ depth }) => depth > 1 && depth < 5)
|
||||
.map((header) => (
|
||||
<li class={`header-link depth-${header.depth} ${activeId === header.slug ? 'active' : ''}`.trim()}>
|
||||
<a href={`#${header.slug}`}>{header.text}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<EditOnGithub href={editHref} />
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default DocSidebar;
|
|
@ -1,26 +0,0 @@
|
|||
import type { FunctionalComponent } from 'preact';
|
||||
import { h } from 'preact';
|
||||
|
||||
const EditOnGithub: FunctionalComponent<{ href: string }> = ({ href }) => {
|
||||
return (
|
||||
<a class="edit-on-github" href={href}>
|
||||
<svg
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
height="1em"
|
||||
width="1em"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 438.549 438.549"
|
||||
stroke="none"
|
||||
class="icon-7f6730be--text-3f89f380"
|
||||
>
|
||||
<g>
|
||||
<path d="M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14.954 8.945.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-.571-.049-5.708-.144-15.417a2549.81 2549.81 0 0 1-.144-25.406l-6.567 1.136c-4.187.767-9.469 1.092-15.846 1-6.374-.089-12.991-.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-.572-1.335-.098-2.43 1.427-3.289 1.525-.859 4.281-1.276 8.28-1.276l5.708.853c3.807.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-.476 16.274-1.423 4.565-.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-.01-39.771-9.818-76.454-29.414-110.049z"></path>
|
||||
</g>
|
||||
</svg>
|
||||
<span>Edit on GitHub</span>
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditOnGithub;
|
|
@ -1,52 +0,0 @@
|
|||
---
|
||||
export interface Props {
|
||||
title: string;
|
||||
type?: 'tip' | 'warning' | 'error'
|
||||
}
|
||||
const { type = 'tip', title } = Astro.props;
|
||||
---
|
||||
|
||||
<aside class={`note type-${type}`}>
|
||||
{title && <label>{title}</label>}
|
||||
<slot />
|
||||
</aside>
|
||||
|
||||
<style>
|
||||
.note {
|
||||
--padding-block: 1rem;
|
||||
--padding-inline: 1.25rem;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
padding: var(--padding-block) var(--padding-inline);
|
||||
margin-left: calc(var(--padding-inline) * -1);
|
||||
margin-right: calc(var(--padding-inline) * -1);
|
||||
|
||||
background: var(--theme-bg-offset);
|
||||
border-left: calc(var(--padding-inline) / 2) solid var(--color);
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.note label {
|
||||
font-weight: 500;
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
/* .note :global(a) {
|
||||
color: var(--color);
|
||||
} */
|
||||
|
||||
.note.type-tip {
|
||||
--color: var(--color-green);
|
||||
--color-rgb: var(--color-green-rgb);
|
||||
}
|
||||
.note.type-warning {
|
||||
--color: var(--color-yellow);
|
||||
--color-rgb: var(--color-yellow-rgb);
|
||||
}
|
||||
.note.type-error {
|
||||
--color: var(--color-red);
|
||||
--color-rgb: var(--color-red-rgb);
|
||||
}
|
||||
</style>
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
import { sidebar } from '../config.ts';
|
||||
---
|
||||
|
||||
<nav>
|
||||
<ul class="nav-groups">
|
||||
{sidebar.map(category => (
|
||||
<li>
|
||||
<div class="nav-group">
|
||||
<h4 class="nav-group-title"><a href={`${Astro.site}${category.link}`}>{category.text}</a></h4>
|
||||
<ul>
|
||||
{category.children.map(child => (
|
||||
<li class="nav-link"><a href={`${Astro.site}${child.link}`}>{child.text}</a></li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
|
@ -1,71 +0,0 @@
|
|||
import type { FunctionalComponent } from 'preact';
|
||||
import { h, Fragment } from 'preact';
|
||||
import { useState, useEffect } from 'preact/hooks';
|
||||
|
||||
const themes = ['system', 'light', 'dark'];
|
||||
|
||||
const icons = [
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M3 5a2 2 0 012-2h10a2 2 0 012 2v8a2 2 0 01-2 2h-2.22l.123.489.804.804A1 1 0 0113 18H7a1 1 0 01-.707-1.707l.804-.804L7.22 15H5a2 2 0 01-2-2V5zm5.771 7H5V5h10v7H8.771z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>,
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>,
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
|
||||
</svg>,
|
||||
];
|
||||
|
||||
const ThemeToggle: FunctionalComponent = () => {
|
||||
const [theme, setTheme] = useState(themes[0]);
|
||||
|
||||
useEffect(() => {
|
||||
const user = localStorage.getItem('theme');
|
||||
if (!user) return;
|
||||
setTheme(user);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const root = document.documentElement;
|
||||
if (theme === 'system') {
|
||||
localStorage.removeItem('theme');
|
||||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
root.classList.add('theme-dark');
|
||||
} else {
|
||||
root.classList.remove('theme-dark');
|
||||
}
|
||||
} else {
|
||||
localStorage.setItem('theme', theme);
|
||||
if (theme === 'light') {
|
||||
root.classList.remove('theme-dark');
|
||||
} else {
|
||||
root.classList.add('theme-dark');
|
||||
}
|
||||
}
|
||||
}, [theme]);
|
||||
|
||||
return (
|
||||
<div id="theme-toggle">
|
||||
{themes.map((t, i) => {
|
||||
const icon = icons[i];
|
||||
const checked = t === theme;
|
||||
return (
|
||||
<label className={checked ? 'checked' : ''}>
|
||||
{icon}
|
||||
<input type="radio" name="theme-toggle" checked={checked} value={t} title={`Use ${t} theme`} aria-label={`Use ${t} theme`} onChange={() => setTheme(t)} />
|
||||
</label>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ThemeToggle;
|
|
@ -1,10 +0,0 @@
|
|||
export const sidebar = [
|
||||
{
|
||||
text: 'Introduction',
|
||||
link: '', // No leading slash needed, so this links to the homepage
|
||||
children: [
|
||||
{ text: 'Getting Started', link: 'getting-started' },
|
||||
{ text: 'Example', link: 'example' },
|
||||
],
|
||||
},
|
||||
];
|
|
@ -1,232 +0,0 @@
|
|||
---
|
||||
import ArticleFooter from '../components/ArticleFooter.astro';
|
||||
import SiteSidebar from '../components/SiteSidebar.astro';
|
||||
import ThemeToggle from '../components/ThemeToggle.tsx';
|
||||
import DocSidebar from '../components/DocSidebar.tsx';
|
||||
|
||||
const { content } = Astro.props;
|
||||
const headers = content?.astro?.headers;
|
||||
let editHref = Astro?.request?.url?.pathname?.slice(1) ?? '';
|
||||
if (editHref === '') editHref = `index`;
|
||||
editHref = `https://github.com/snowpackjs/astro/tree/main/examples/doc/src/pages/${editHref}.md`
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>{content.title}</title>
|
||||
|
||||
<link rel="stylesheet" href="/index.css" />
|
||||
<script src="/theme.js" />
|
||||
<link rel="icon"
|
||||
type="image/svg+xml"
|
||||
href="/favicon.svg">
|
||||
|
||||
<style>
|
||||
body {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: 3.5rem 1fr;
|
||||
--gutter: 0.5rem;
|
||||
--doc-padding: 2rem;
|
||||
}
|
||||
|
||||
header {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--theme-bg-offset);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.layout {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
grid-template-columns: minmax(var(--gutter), 1fr) minmax(0, var(--max-width)) minmax(var(--gutter), 1fr);
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.menu-and-logo {
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
nav.layout {
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
nav.layout :global(> :nth-child(1)) {
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
#site-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25em;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
line-height: 1;
|
||||
color: var(--theme-text);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#site-title:hover,
|
||||
#site-title:focus {
|
||||
color: var(--theme-text-light);
|
||||
}
|
||||
|
||||
#site-title h1 {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
max-width: 64ch;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.layout :global(> *) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
max-height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding: var(--doc-padding) 0;
|
||||
}
|
||||
|
||||
#sidebar-nav {
|
||||
display: none;
|
||||
max-height: 100vh;
|
||||
padding: var(--doc-padding) 0;
|
||||
}
|
||||
|
||||
#article {
|
||||
padding: var(--doc-padding) var(--gutter);
|
||||
grid-column: 2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
max-width: 64ch;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.content > main {
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
#sidebar-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 64em) {
|
||||
.menu-and-logo button {
|
||||
display: none;
|
||||
}
|
||||
.layout {
|
||||
grid-template-columns: 20rem minmax(0, 1fr);
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
#article {
|
||||
grid-column: 2;
|
||||
}
|
||||
#sidebar-nav {
|
||||
display: flex;
|
||||
}
|
||||
#sidebar-content {
|
||||
/* display: flex; */
|
||||
grid-column: 3;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
display: contents;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 88em) {
|
||||
.layout {
|
||||
grid-template-columns: minmax(var(--gutter), 1fr) 20rem minmax(0, var(--max-width)) 16rem minmax(var(--gutter), 1fr);
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
#sidebar-nav,
|
||||
.nav-wrapper :global(:nth-child(1)) {
|
||||
grid-column: 2;
|
||||
}
|
||||
#article,
|
||||
.nav-wrapper :global(:nth-child(2)) {
|
||||
grid-column: 3;
|
||||
}
|
||||
#sidebar-content,
|
||||
.nav-wrapper :global(:nth-child(3)) {
|
||||
display: flex;
|
||||
grid-column: 4;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<nav class="layout">
|
||||
<div class="nav-wrapper">
|
||||
<div class="menu-and-logo flex">
|
||||
<button id="menu-toggle">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
</button>
|
||||
<a id="site-title" href="/">
|
||||
<svg width="1em" height="1em" viewBox="0 0 340 340" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M320 170C320 170 296.88 171.746 267.428 188.75C237.975 205.754 205.754 237.975 188.75 267.428C171.746 296.88 170 320 170 320C170 320 168.254 296.88 151.25 267.428C134.246 237.975 102.025 205.754 72.5721 188.75C43.1197 171.746 20 170 20 170C20 170 43.1197 168.254 72.5721 151.25C102.025 134.246 134.246 102.025 151.25 72.5721C168.254 43.1197 170 20 170 20C170 20 171.746 43.1197 188.75 72.5721C205.754 102.025 237.975 134.246 267.428 151.25C296.88 168.254 320 170 320 170Z" fill="currentColor"/>
|
||||
</svg>
|
||||
<h1>Astroid</h1>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div />
|
||||
|
||||
<div>
|
||||
<ThemeToggle:idle />
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="layout">
|
||||
<aside class="sidebar" id="sidebar-nav">
|
||||
<SiteSidebar />
|
||||
</aside>
|
||||
<div id="article">
|
||||
<article class="content">
|
||||
<main>
|
||||
<h1>{content.title}</h1>
|
||||
<slot />
|
||||
</main>
|
||||
<ArticleFooter />
|
||||
</article>
|
||||
</div>
|
||||
<aside class="sidebar" id="sidebar-content">
|
||||
<DocSidebar:idle headers={headers} editHref={editHref} />
|
||||
</aside>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -1,34 +0,0 @@
|
|||
---
|
||||
title: Markdown Example
|
||||
layout: ../layouts/Main.astro
|
||||
---
|
||||
|
||||
This is a fully-featured page, written in Markdown!
|
||||
|
||||
## Section A
|
||||
|
||||
Lorem ipsum dolor sit amet, **consectetur adipiscing elit**. Sed ut tortor _suscipit_, posuere ante id, vulputate urna. Pellentesque molestie aliquam dui sagittis aliquet. Sed sed felis convallis, lacinia lorem sit amet, fermentum ex. Etiam hendrerit mauris at elementum egestas. Vivamus id gravida ante. Praesent consectetur fermentum turpis, quis blandit tortor feugiat in. Aliquam erat volutpat. In elementum purus et tristique ornare. Suspendisse sollicitudin dignissim est a ultrices. Pellentesque sed ipsum finibus, condimentum metus eget, sagittis elit. Sed id lorem justo. Vivamus in sem ac mi molestie ornare.
|
||||
|
||||
## Section B
|
||||
|
||||
Nam quam dolor, pellentesque sed odio euismod, feugiat tempus tellus. Quisque arcu velit, ultricies in faucibus sed, ultrices ac enim. Nunc eget dictum est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ex nisi, egestas mollis ultricies ut, laoreet suscipit libero. Nam condimentum molestie turpis. Sed vestibulum sagittis congue. Maecenas tristique enim et tincidunt tempor. Curabitur ac scelerisque nulla, in malesuada libero. Praesent eu tempus odio. Pellentesque aliquam ullamcorper quam at gravida. Sed non fringilla mauris. Aenean sit amet ultrices erat. Vestibulum congue venenatis tortor, nec suscipit tortor. Aenean pellentesque mauris eget tortor tincidunt pharetra.
|
||||
|
||||
## Section C
|
||||
|
||||
```markdown
|
||||
---
|
||||
layout: ../layouts/Main.astro
|
||||
---
|
||||
|
||||
# Markdown example
|
||||
|
||||
This is a fully-featured page, written in Markdown!
|
||||
|
||||
## Section A
|
||||
|
||||
Lorem ipsum dolor sit amet, **consectetur adipiscing elit**. Sed ut tortor _suscipit_, posuere ante id, vulputate urna. Pellentesque molestie aliquam dui sagittis aliquet. Sed sed felis convallis, lacinia lorem sit amet, fermentum ex. Etiam hendrerit mauris at elementum egestas. Vivamus id gravida ante. Praesent consectetur fermentum turpis, quis blandit tortor feugiat in. Aliquam erat volutpat. In elementum purus et tristique ornare. Suspendisse sollicitudin dignissim est a ultrices. Pellentesque sed ipsum finibus, condimentum metus eget, sagittis elit. Sed id lorem justo. Vivamus in sem ac mi molestie ornare.
|
||||
|
||||
## Section B
|
||||
|
||||
Nam quam dolor, pellentesque sed odio euismod, feugiat tempus tellus. Quisque arcu velit, ultricies in faucibus sed, ultrices ac enim. Nunc eget dictum est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ex nisi, egestas mollis ultricies ut, laoreet suscipit libero. Nam condimentum molestie turpis. Sed vestibulum sagittis congue. Maecenas tristique enim et tincidunt tempor. Curabitur ac scelerisque nulla, in malesuada libero. Praesent eu tempus odio. Pellentesque aliquam ullamcorper quam at gravida. Sed non fringilla mauris. Aenean sit amet ultrices erat. Vestibulum congue venenatis tortor, nec suscipit tortor. Aenean pellentesque mauris eget tortor tincidunt pharetra.
|
||||
```
|
|
@ -1,59 +0,0 @@
|
|||
---
|
||||
title: Getting Started
|
||||
layout: ../layouts/Main.astro
|
||||
---
|
||||
|
||||
This template already provides your pages with a side bar navigation (on the left) for your pages, and a content navigation (on the right) for your sections.
|
||||
|
||||
## Page navigation
|
||||
|
||||
The page navigation, through the side bar on the left, needs to be manually updated. Open the `config.ts` file and you will find the following structure:
|
||||
|
||||
```ts
|
||||
export const sidebar = [
|
||||
{
|
||||
text: 'Introduction',
|
||||
link: '', // No leading slash needed, so this links to the homepage
|
||||
children: [
|
||||
{ text: 'Getting Started', link: 'getting-started' },
|
||||
{ text: 'Example', link: 'example' },
|
||||
],
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
You can change this file to match the pages you want to display, the items within `children` can also have children elements, but only the first level and second levels will be displayed.
|
||||
|
||||
The page navigation is generated in the `src/components/SiteSidebar.astro`, so if you want to change the depth of elements displayed, styles, etc, that's the place to go.
|
||||
|
||||
## Section navigation
|
||||
|
||||
The section navigation, through the side bar on the right, is automatically generated by the `src/components/DocSidebar.tsx` file, it uses the meta-data from markdown files to generate the structure you see.
|
||||
|
||||
By default only elements from depth 2 to 5 will be displayed, and at the moment doesn't work for `.astro files`.
|
||||
|
||||
## Other Components
|
||||
|
||||
### Footer
|
||||
|
||||
You can edit your footer here `src/components/ArticleFooter.astro`, at the moment it is composed of a list of avatars. You can generate your own avatar [here](https://getavataaars.com/) and replace the ones from `AvatarList.astro`.
|
||||
|
||||
### Theme
|
||||
|
||||
The `src/components/ThemeToggle.tsx` is only responsible for applying the theme, to change the theme colors see `public/theme.css`
|
||||
|
||||
## Documentation
|
||||
|
||||
For more information on how to use Astro components, check the documentation pages:
|
||||
|
||||
- [General Instructions](https://github.com/snowpackjs/astro#readme)
|
||||
- [astro.config.mjs](https://github.com/snowpackjs/astro/blob/main/docs/config.md)
|
||||
- [API](https://github.com/snowpackjs/astro/blob/main/docs/api.md)
|
||||
- [Command Line Interface](https://github.com/snowpackjs/astro/blob/main/docs/cli.md)
|
||||
- [Collections](https://github.com/snowpackjs/astro/blob/main/docs/collections.md)
|
||||
- [Development Server](https://github.com/snowpackjs/astro/blob/main/docs/dev.md)
|
||||
- [Markdown](https://github.com/snowpackjs/astro/blob/main/docs/markdown.md)
|
||||
- [Publishing Astro components](https://github.com/snowpackjs/astro/blob/main/docs/publishing.md)
|
||||
- [Renderers](https://github.com/snowpackjs/astro/blob/main/docs/renderers.md)
|
||||
- [Styling](https://github.com/snowpackjs/astro/blob/main/docs/styling.md)
|
||||
- [.astro Syntax](https://github.com/snowpackjs/astro/blob/main/docs/syntax.md)
|
240
docs/blog/island-architecture.md
Normal file
240
docs/blog/island-architecture.md
Normal file
|
@ -0,0 +1,240 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Island Architecture
|
||||
draft: true
|
||||
---
|
||||
<!--
|
||||
@aFuzzyBear: I have been spending most the day learning more about Island Architecture, wrote plenty of notes, listened to Fred K Schott's interview on Speakeasy(https://www.youtube.com/watch?v=mgkwZqVkrwo) and the interview with Jason Lengstrof (https://www.youtube.com/watch?v=z15YLsLMtu4)
|
||||
Figured I might give writing this a wee go,
|
||||
|
||||
I wanted to take this from the direction of it being more of a critique of the past and present state of affairs in web dev
|
||||
Post structure:
|
||||
1)Start with an introduction to Islands Arch
|
||||
2)Talk about the different Architectures that can be used in Web-dev
|
||||
3)MVC/StaticSites - SPA's
|
||||
4)Frameworks, get some external links onto the page
|
||||
4)Moving to ESM
|
||||
5)Benefits of ESM
|
||||
6)
|
||||
|
||||
-->
|
||||
|
||||
<!-- Intro -->
|
||||
|
||||
> "No man is an island. However, Web Components should be"
|
||||
|
||||
The concept behind Island architecture comes from [Jason Miller](https://twitter.com/_developit), The creator of [Preact](https://preactjs.com/) and a Google, DevRel Engineer.
|
||||
|
||||
In the summer of 2020, he managed to formulated his thoughts of how web architecture should be, in the idyllic sense, and placed them onto his [blog post](https://jasonformat.com/islands-architecture/).
|
||||
|
||||
His seminal post outlines and discusses the general concept of 'islands' as an architectural design process that could be used in Web Development, allowing for better improvements in overall site performance, SEO, UX, and everywhere else. His given explanation describing this new paradigm, was extraordinarily succinct:
|
||||
|
||||
> "The general idea of an *“Islands”* architecture is deceptively simple: Render HTML pages on the server, and inject placeholders or slots around highly dynamic regions. These placeholders/slots contain the server-rendered HTML output from their corresponding widget. They denote regions that can then be "hydrated" on the client into small self-contained widgets, reusing their server-rendered initial HTML."-Jason Miller
|
||||
|
||||
To develop a better understanding of what Jason meant with his proposal, let's quickly explore the backdrop, before we explain 'Island Architecture' and how it is applied into Astro as our primary ethos.
|
||||
|
||||
## Programming Paradigms
|
||||
|
||||
Think of a simple webpage. On which are many different types of components that are shown on this page, components that are shared across the site, others contain fixed content, some are a bit more elaborate that may perhaps use different state's or need to fetch multiple data streams from external sources.
|
||||
|
||||
Such an site would would have very few actual 'moving' pieces, or *dynamic* elements. For the most part the content tends to be fixed, and static.
|
||||
|
||||
In order to allow for dynamism and interactivity we are often left making overly complex solutions to deliver the slightest form of action on the application.
|
||||
|
||||
Complexity becomes inherent in the design process of the application. As a result, developers have to adopt some dogma, that comes from certain architectural design styles and patterns.
|
||||
|
||||
Given the [catalogue of patterns](https://en.wikipedia.org/wiki/List_of_software_architecture_styles_and_patterns) that are available, utilizing the right architecture for the application often comes from hard-to-obtain experience.
|
||||
|
||||
Web developers tend to gravitate towards tried and tested practices, and none fit the requirements better than the [Model-View-Controller](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) (**MVC**) design pattern.
|
||||
|
||||
Where the **Model** contains the data structures and logic that governs the use of the data in the application. **Views** are the visual representation of the data that the user sees, and the **Controller** connects the views to their relevant data *Models* based on their interactions with the User.
|
||||
|
||||
This design pattern works well for our [client-server](https://en.wikipedia.org/wiki/Client%E2%80%93server_model) based applications. Since the models are placed on the *servers*, the views that are sent back over the wire tend to be static *documents*, controllers are sent along with the static files to facilitate the behaviours that web developers created for their application, in the form of *scripts*.
|
||||
|
||||
## Rise of the Frameworks
|
||||
|
||||
A vast swathe of libraries, frameworks and tooling rose up to meet the challenges of providing a Developer Experience (DX) that would let them create their applications, *'freely'*.
|
||||
|
||||
Helping to abstract away much of the complexity needed in implementing architectural design decisions into their application.
|
||||
|
||||
The likes of; [ASP.NET](https://dotnet.microsoft.com/learn/aspnet/what-is-aspnet-core) and [Blazor](https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor) for [.NET](https://dotnet.microsoft.com/), [Ruby On Rails](https://rubyonrails.org/), [Laravel](https://laravel.com/) & [Symphony](https://symfony.com/) for [PHP](https://www.php.net/), are examples of the MVC patterns seen in other server-side programming languages.
|
||||
|
||||
For along time, JavaScript was solely restricted to the Browser, then [Node.js](https://nodejs.org/en/) appeared. Node.js is a standalone JavaScript runtime built on the Chrome V8 engine.
|
||||
|
||||
This was a seismic shift that occurred in Web Development, by allowing JavaScript to escape the browser and operate on the server, developers could use JS on both; Front & Back-ends, when developing their applications.
|
||||
|
||||
Within the new JavaScript + Node ecosystem, JS MVC frameworks began to appear, e.g: [BackboneJS](https://backbonejs.org/), [ExpressJS](https://expressjs.com/), [Ember](https://emberjs.com/), [MeteorJS](https://www.meteor.com/), to name but a few.
|
||||
|
||||
This pattern of statically generated content on the server was becoming a bit of a performance bottleneck.
|
||||
|
||||
Where some asset-heavy page would take longer to render on the server than a lighter page.
|
||||
|
||||
This would block subsequent requests being made to the server, and more crucially responses being sent back from the server.
|
||||
|
||||
Server performance and optimisation only addressed the problem so far, but with larger payloads and pages being sent more frequently, something had to be done.
|
||||
|
||||
Frameworks, rose again to the challenge of delivering a better User Experience (UX) began to ship [Single Page Applications](https://en.wikipedia.org/wiki/Single-page_application) (**SPA**) to the client.
|
||||
|
||||
SPA's became a fast and effective ways to sending feature-rich applications to the client without the load being placed on the server.
|
||||
|
||||
Instead rendering the application would now be carried out wholly on the client device. Thus allowing the Server to send a single, simple, page to the client.
|
||||
|
||||
There are many benefits in providing a SPA to Clients. SPA's never needs a page refresh, since all the files (HTML/CSS/JS) had already been sent over the wire.
|
||||
|
||||
This only required the End-User's web browser to then read and render the application to the screen.
|
||||
|
||||
But SPA's came with their own hidden cost that comes with abstracting away the complexity. Recognising the many issues with SPA's from a holistic DX to a seamless UX/UI.
|
||||
|
||||
Frameworks began to appear in the ecosystem that allowed developers to build even more advanced Single-Page-Applications.
|
||||
|
||||
Some of these were developed by industry leaders, such as Google with their [Angular Project](https://angularjs.org/), [React](https://reactjs.org/) which was open sourced by Facebook. Or by the JS community themselves driving changes with [Preact](https://preactjs.com/), [Vue](https://vuejs.org/) and [Svelte](https://svelte.dev/), [Webpack](https://webpack.js.org/) & [Babel](https://babeljs.io/setup)
|
||||
|
||||
## The Status Quo
|
||||
|
||||
Its slightly hubris to suggest that the web development ecosystem had at all settled for any period of time, well at least long enough for a Status Quo to coalesce.
|
||||
|
||||
However, given the vibrancy and versatility of the ecosystem, a status quo had indeed began to take hold.
|
||||
|
||||
Rooted in the deepest annals of the developers psyche, was the slow conformity towards embracing UI frameworks to build the whole site as applications instead of the dynamic components that it was meant for.
|
||||
|
||||
Everything ended up being sent to the Client. From Rendering to Routing, bundled payload sizes drastically increased, and client devices were asked to do a lot more.
|
||||
|
||||
By placing the onus on the client, Server stress was indeed lessened. But there was a cost to this status quo.
|
||||
|
||||
The End-User experience was drastically suffering, for their devices now became the bottleneck, unable to execute the massive payloads that were being sent back from the server.
|
||||
|
||||
As demonstrated, JavaScript and its community are quick to change in certain places and slow in others. The gradual adoption of [EcmaScript Modules](https://tc39.es/ecma262/#sec-modules)(**ESM**) as a standard to the JavaScript spec was a complete sea-change to the ecosystem.
|
||||
|
||||
Prior to the formalisation of ESM, module usage in JS were often limited to libraries and were difficult to use outside the browser.
|
||||
|
||||
Using community developed conventions, helped push the goal of a modular ecosystem with [CommonJS](https://en.wikipedia.org/wiki/CommonJS)(**CJS**).
|
||||
|
||||
Node v12 shipped with ESM Modules as part of the standard in node. Signalling the start of something entirely new.
|
||||
|
||||
## The Great Migration
|
||||
|
||||
ESM adoption was indeed slow, the gradual migration from `require()` to `import()` took a while.
|
||||
|
||||
Now developing in an ESM world, allows for certain advantages to be exploited.
|
||||
|
||||
This wanting exploitation of new features have given way for another influx of new libraries, frameworks, tooling and a whole suite of new methods of writing JS.
|
||||
|
||||
We are now experiencing new tools in the ecosystem that feature ESM as defaults.
|
||||
|
||||
By doing so we can take full advantage of unbundled developer environments, allowing for projects to start-up in the tens of milliseconds, instead of whole seconds and full minutes.
|
||||
|
||||
Using ESM in the Browser, tools can build once and cache forever. Tree-shaking and code optimisations can occur, more frequently and with greater efficacy. Reducing massive bundle sizes down to a few hundred Kilobytes.
|
||||
|
||||
Tools like [Snowpack](https://www.snowpack.dev/) and [Vite](https://vitejs.dev/) introduce an whole new experience that developers were previously denied in their development process and that is speed.
|
||||
|
||||
With cut-edge DX features like [HMR](https://npm.io/package/esm-hmr) has quickly became the industry de facto, and build times reduced by a factor of 100x.
|
||||
|
||||
This new generation of ESM tools is extremely encouraging for web developers.
|
||||
|
||||
## A Brave New World
|
||||
|
||||
Into this new age ESM world, we have had a dearth of innovation from the established frameworks to address some of the root issues that plagued web development over its time.
|
||||
|
||||
Basic questions of : Websites or WebApp's were still unresolved. Where to render the site, on the server or on the client, perhaps a bit of both? What determines the need for dynamic content and what specifies content to be static?
|
||||
|
||||
Witnessing frameworks slowly go full circle and return to Server-Side-Rendering (*SSR*) their applications was in part only allowed to be considered in an ESM world, however it was bit of an admission of culpability of sorts.
|
||||
|
||||
By inadvertently admitting that the current model is flawed, opened up the space for a new form of discourse to enter, and help redefine the ecosystem moving forward.
|
||||
|
||||
SSR frameworks such as [Next.js](https://nextjs.org/), [Nuxt.js](https://nuxtjs.org/), [SvelteKit](https://kit.svelte.dev/), did help address some of the underling questions, within the current paradigm.
|
||||
|
||||
Developing methods and techniques to deliver production-stable SSR along with tooling and support for the developer.
|
||||
|
||||
But in a new age, retaining previously disputed tenants only aided the lack of innovation in this new dawn.
|
||||
|
||||
Jason Miller's formulations of an 'Island'-styled approach only augments the discussion with fresh new ideas about Website and Application development.
|
||||
|
||||
## The Golden Isles and its many Islands
|
||||
|
||||
In the introduction we placed a quote from Jason, describing the general concept of Island architecture. Let's revisit his words, since we have a better understanding of the context in which this is being proposed.
|
||||
|
||||
Jason asks us to think of a Island architecture as a static HTML document. One that is rendered entirely on the server.
|
||||
|
||||
The document contains multiple separate embedded applications, that are injected into placeholders or '*slots*', which form dynamic regions on the page.
|
||||
|
||||
The Server renders HTML outputs form each of these dynamic components, and places them onto the static document being sent back down to the End-User.
|
||||
|
||||
These slots, of dynamic regions, can then be '*hydrated*'. [Hydration](https://en.wikipedia.org/wiki/Hydration_(web_development)) is a process that allows for Client-Sided JS to convert and make static HTML, dynamic, reusing their initial server-rendered HTML.
|
||||
|
||||
This 'micro' architecture is similar to both 'micro-frontends' and 'micro-services'. Both share the concept of breaking applications into small indivisible units. But the problem is that a lot of the small modular units are rarely composed in HTML.
|
||||
|
||||
With Island-Architecture, he proposes a form of progressive enhancement for the dynamic components by using a technique known as *Partial Hydration*.
|
||||
|
||||
Lets look at this following analogy:
|
||||
|
||||
On our Static page, we have an image carousel. Such carousel needs to have some form of interactivity to load the next image after a certain amount of time has elapsed, along with navigation and pagination buttons on the carousel.
|
||||
|
||||
To do this we would need to implement some behaviour on our carousel.
|
||||
|
||||
In the traditional sense, we might be using a React Component to help create the aforementioned experience. In order to do this we would have too include the React-runtime plugin as a top-level `<script>` within our HTML document.
|
||||
|
||||
This means for our page, we need to wait for React to be fetched and downloaded, then parsed and executed, have it wait for the page to display the carousel before we receive the behaviour and functionality we expect from our small dynamic component.
|
||||
|
||||
Instead of this laborious process, one would simply render the carousel in HTML on the server and have a dedicated `<script>` that is emitted when the component for the carousel is displayed.
|
||||
|
||||
This would then load the functionality for the carousel in-place, transforming it instantly into a dynamic image slide show, with navigation.
|
||||
|
||||
## Island Hydration
|
||||
|
||||
By now the idea of Island-architecture must be settling in, and one must be thinking, this is just [Progressive Hydration](https://en.wikipedia.org/wiki/Hydration_(web_development)#Progressive_rehydration), and you wouldn't be overly off mark.
|
||||
|
||||
Progressive Hydration that is used in frameworks like: Angluar, React, Preact, Vue. Are individual components, which are loaded and then initialised over a period of time.
|
||||
|
||||
Using scheduling processes, and accounting for things like viewport visibility, content value, probability of interaction etc. They can abstract away the intricacies and delivery this form of hydration for developers.
|
||||
|
||||
By using Island styled components, this form of hydration essentially comes for **free**.
|
||||
|
||||
Since the larger dynamic components on a page are being initialised separately, not progressively. The difference lets individual regions on the page to become interactive without the page requiring to first load anything.
|
||||
|
||||
This expands further, as it doesn't need any form of ['Top-down Rendering'](https://developers.google.com/web/fundamentals/performance/rendering).
|
||||
|
||||
Since there is no outer `<div id='root'>` element that needs to be initialised before the inner contents can be exposed.
|
||||
|
||||
Every region of the page is an isolated unit, an island, on its own, connected to others by the HTML page. With such an approach the benefits do begin to stack up.
|
||||
|
||||
A key benefit is seen with the site performance. Since isolation is inherent, if a single issue affects a component, it wouldn't affect the other *islands* on the page.
|
||||
|
||||
## Exploring the Island
|
||||
|
||||
As we explore further into the Island, we can see immediate trade differences between framework produced SSR solutions and those that could be provided by using Island Architecture.
|
||||
|
||||
Quickly wandering back to the Status Quo for a brief interlude. We use SSR with SPA's to help tackle the downside of SPA's and its SEO. Appealing to the search engines in this manner has another negative affect on the UX.
|
||||
|
||||
>"...visitors are left waiting for the actual functionality of a page to arrive while staring at a frustratingly fake version of that page." - Jason Miller
|
||||
|
||||
There are other issues that stem from traditional SSR, and being idly unawares of such performance pitfalls, gives rise to an orchestra of potential problems.
|
||||
|
||||
Further compounded with misconceptions on implementations and utilisations of solid SSR techniques, this practice is increasingly prominent amongst the Status Quoticians.
|
||||
|
||||
The one most obvious drawback with SSR is the amount of work JS has to do during the initial page load, is far excessive than is necessary, and is extremely inefficient use of resources.
|
||||
|
||||
We find with our "Islands" model, that with Server rendering is a fundamental part of how pages are delivered to the browser.
|
||||
|
||||
The responded HTML, would still contain all the rendered content that the user requested. With some islands yet to engage their client-sided interactivity. The document sent should contain all the content that the User would need.
|
||||
|
||||
An example of this would be a product page for a e-commerce business. A product page, using the Islands model would contain that products description, price etc, Having the dynamic components becoming interactive on demand.
|
||||
|
||||
We also discover that with the Islands model we have better accessibility and discoverability of our elements and the contents within.
|
||||
|
||||
Less code is eventually shipped from each island which is a massive cost-saving benefit.
|
||||
|
||||
However the conceptual idea of using Islands from a Web developers viewpoint is that, we get to come full circle and begin to deliver lightening fast user experiences without having the previous trade-offs and penalties that came from previous design models.
|
||||
|
||||
They're plenty of more important discoveries yet to be made when exploring the Island Architecture model in more detail.
|
||||
|
||||
Jason finished his post with the following:
|
||||
|
||||
> "It's possible...that adopting a model like this requires more up-front design thinking. There are far few batteries-included options available ...Who knows, maybe we can fix that." - August 2020
|
||||
|
||||
## Astrolands
|
||||
|
||||
<!-- Conclusion, final words. Here tie in Astro -->
|
||||
|
||||
Here at Astro, we fully embrace the principles ideas behind Jason's 'Island Architecture'. As a result, we have been hard at work trying to apply this new innovative concept into Web Development and the JS ecosystem.
|
||||
|
||||
We would like to take this time to encourage you to start exploring how Astro accomplishes this. And experience how easy it is to adopt as an architectural design philosophy.
|
|
@ -1,3 +1,10 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Astro Components
|
||||
---
|
||||
|
||||
|
||||
|
||||
## ✨ `.astro` Syntax
|
||||
|
||||
Astro comes with its own server-side, component-based templating language. Think of it as HTML enhanced with the full power of JavaScript.
|
||||
|
@ -197,3 +204,5 @@ If you’d prefer to organize assets alongside Astro components, you may import
|
|||
### TODO: Composition (Slots)
|
||||
|
||||
[code-ext]: https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode
|
||||
|
||||
|
72
docs/core-concepts/astro-pages.md
Normal file
72
docs/core-concepts/astro-pages.md
Normal file
|
@ -0,0 +1,72 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Astro Pages
|
||||
---
|
||||
|
||||
**Pages** are a special type of [Astro Component](./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.
|
||||
|
||||
Astro also supports Markdown for content-heavy pages, like blog posts and documentation. See [Markdown Content](./markdown-content.md) for more information on writing pages with Markdown.
|
||||
|
||||
## File-based Routing
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
## Data Loading
|
||||
|
||||
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.**
|
||||
|
||||
```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);
|
||||
---
|
||||
<!-- Output the result to the page -->
|
||||
<div>{JSON.stringify(data)}</div>
|
||||
```
|
||||
### `fetch()`
|
||||
|
||||
Astro pages have access to the global `fetch()` function in their setup script. `fetch()` is a native JavaScript API ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)) that lets you make HTTP requests for things like APIs and resources.
|
||||
|
||||
Even though Astro component scripts run inside of Node.js (and not in the browser) Astro provides this native API so that you can fetch data at page build time.
|
||||
|
||||
### Top-level await
|
||||
|
||||
`await` is another native JavaScript feature that lets you await the response of some asynchronous promise ([MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)). Astro supports `await` in the top-level of your component script.
|
||||
|
||||
## 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](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)) and `<body>` ([MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body)).
|
||||
|
||||
`<!doctype html>` is optional, and will be added automatically.
|
||||
|
||||
```astro
|
||||
---
|
||||
// Example: HTML page skeleton
|
||||
---
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Document title</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello, world!</h1>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
# 🍱 Collections
|
||||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Collections
|
||||
---
|
||||
|
||||
## What are Collections?
|
||||
|
||||
Astro Collections help you break up a larger set of data into multiple pages. Examples of use-cases include:
|
||||
**Collections** are a special type of [Page](./astro-pages) that help you generate multiple pages from a larger set of data. Example use-cases include:
|
||||
|
||||
- Pagination: `/posts/1`, `/posts/2`, etc.
|
||||
- Grouping content by author: `/author/fred`, `/author/matthew`, etc.
|
||||
|
@ -10,9 +11,9 @@ Astro Collections help you break up a larger set of data into multiple pages. Ex
|
|||
- Working with remote data
|
||||
- Mixing remote and local data
|
||||
|
||||
**When to use Collections: When you need to reuse a single template to generate multiple pages from a larger dataset.** If you just want to generate a single page (ex: a long list of every post on your site) then you can just fetch that data on a normal Astro page without using the Collection API.
|
||||
**Use a Collection when you need to generate multiple pages from a single template.** If you just want to generate a single page (ex: a long list of every post on your site) then you can just fetch that data on a normal Astro page without using the Collection API.
|
||||
|
||||
## Collections API
|
||||
## Using Collections
|
||||
|
||||
To create a new Astro Collection, you must do three things:
|
||||
|
37
docs/core-concepts/component-hydration.md
Normal file
37
docs/core-concepts/component-hydration.md
Normal file
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: React, Svelte, Vue, etc.
|
||||
---
|
||||
|
||||
By default, Astro generates your site with zero client-side JavaScript. If you use any frontend UI components (React, Svelte, Vue, etc.) Astro will automatically render them to HTML and strip away any client-side JavaScript. This keeps your site default-fast.
|
||||
|
||||
```
|
||||
---
|
||||
import MyReactComponent from '../components/MyReactComponent.jsx';
|
||||
---
|
||||
<!-- By default: Astro renders this to HTML
|
||||
and strips away all JavaScript. -->
|
||||
<MyReactComponent />
|
||||
```
|
||||
|
||||
However, there are plenty of cases where you might like to include an interactive component on your page:
|
||||
|
||||
- An image carousel
|
||||
- An auto-complete search bar
|
||||
- A mobile sidebar open/close button
|
||||
- A "Buy Now" button
|
||||
|
||||
With Astro, you can hydrate these components individually, without forcing the rest of the page to ship any other unnecesary JavaScript. This technique is called **partial hydration.**
|
||||
## Hydrate Frontend Components
|
||||
|
||||
To hydrate your components in the client, you may use any of the following techniques:
|
||||
|
||||
- `<MyComponent:load />` will render the component on page load.
|
||||
- `<MyComponent:idle />` will use [requestIdleCallback()][mdn-ric] to render the component as soon as main thread is free.
|
||||
- `<MyComponent:visible />` will use an [IntersectionObserver][mdn-io] to render the component when the element enters the viewport.
|
||||
|
||||
## Hydrate Astro Components
|
||||
|
||||
Astro components (`.astro`) are HTML-only templating languages with no client-side runtime. You cannot hydrate an Astro component to run on the client (because the JavaScript front-matter only ever runs at build time).
|
||||
|
||||
If you want to make your Astro component interactive on the client, you should convert it to React, Svelte, or Vue. Otherwise, you can consider adding a `<script>` tag to your Astro component that will run JavaScript on the page.
|
155
docs/core-concepts/layouts.md
Normal file
155
docs/core-concepts/layouts.md
Normal file
|
@ -0,0 +1,155 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Layouts
|
||||
---
|
||||
|
||||
**Layouts** are a special type of [Component](./astro-components) that help you share and reuse common page layouts within your project.
|
||||
|
||||
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.
|
||||
|
||||
## Usage
|
||||
|
||||
Astro layouts support props, slots, and all of the other features of Astro components. Layouts are just normal components, after all!
|
||||
|
||||
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
|
||||
|
||||
```astro
|
||||
---
|
||||
// src/layouts/BaseLayout.astro
|
||||
const {title} = Astro.props;
|
||||
---
|
||||
<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.](/docs/core-concepts/astro-components.md)
|
||||
|
||||
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, to include things
|
||||
|
||||
```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.
|
||||
|
||||
```
|
||||
---
|
||||
// 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 />
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
📚 Learn more about Astro's markdown support in our [Markdown guide](/docs/guides/markdown-content.md).
|
56
docs/core-concepts/project-structure.md
Normal file
56
docs/core-concepts/project-structure.md
Normal file
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Project Structure
|
||||
---
|
||||
|
||||
Astro includes an opinionated folder layout for your project. Every Astro project must include these directories and files:
|
||||
|
||||
- `src/*` - Your project source code (components, pages, etc.)
|
||||
- `public/*` - Your non-code assets (fonts, icons, etc.)
|
||||
- `package.json` - A project manifest.
|
||||
|
||||
The easiest way to set up your new project is with `npm init astro`. Check out our [Installation Guide](/docs/quick-start.md) for a walkthrough of how to set up your project automatically (with `npm init astro`) or manually.
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ ├── layouts/
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
├── public/
|
||||
└── package.json
|
||||
```
|
||||
|
||||
### `src/`
|
||||
|
||||
The src folder is where most of your project source code lives. This includes:
|
||||
|
||||
- [Astro Components](/docs/core-concepts/astro-components.md)
|
||||
- [Pages](/docs/core-concepts/astro-pages.md)
|
||||
- [Markdown](/docs/core-concepts/astro-pages.md)
|
||||
- [Layouts](/docs/core-concepts/astro-pages.md)
|
||||
- [Frontend JS Components](/docs/core-concepts/component-hydration.md)
|
||||
- [Styling (CSS, Sass)](/docs/guides/styling.md)
|
||||
|
||||
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.
|
||||
|
||||
### `src/components`
|
||||
|
||||
[Components](/docs/core-concepts/astro-components.md) 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.
|
||||
|
||||
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.
|
||||
|
||||
### `src/layouts`
|
||||
|
||||
[Layouts](/docs/core-concepts/layouts.md) 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.
|
||||
|
||||
### `src/pages`
|
||||
|
||||
[Pages](/docs/core-concepts/astro-pages.md) contain all pages (`.astro` and `.md` supported) for your website. It is **required** that you put your pages in this directory.
|
||||
|
||||
### `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.
|
||||
|
||||
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`.
|
|
@ -1,4 +1,7 @@
|
|||
# 🪄 Renderers
|
||||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: UI Renderers
|
||||
---
|
||||
|
||||
Astro is designed to support your favorite UI frameworks. [React](https://npm.im/@astrojs/renderer-react), [Svelte](https://npm.im/@astrojs/renderer-svelte), [Vue](https://npm.im/@astrojs/renderer-vue), and [Preact](https://npm.im/@astrojs/renderer-preact) are all built-in to Astro and supported out of the box. No configuration is needed to enable these.
|
||||
|
51
docs/dev.md
51
docs/dev.md
|
@ -1,51 +0,0 @@
|
|||
# Development Server
|
||||
|
||||
The development server comes as part of the Astro CLI. Start the server with:
|
||||
|
||||
```shell
|
||||
astro dev
|
||||
```
|
||||
|
||||
In your project root. You can specify an alternative
|
||||
|
||||
## Special routes
|
||||
|
||||
The dev server will serve the following special routes:
|
||||
|
||||
### /400
|
||||
|
||||
This is a custom **400** status code page. You can add this route by adding a page component to your `src/pages` folder:
|
||||
|
||||
```
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ └── pages/
|
||||
│ └── 400.astro
|
||||
```
|
||||
|
||||
For any URL you visit that doesn't have a corresponding page, the `400.astro` file will be used.
|
||||
|
||||
### /500
|
||||
|
||||
This is a custom **500** status code page. You can add this route by adding a page component to your `src/pages` folder:
|
||||
|
||||
```
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ └── pages/
|
||||
│ └── 500.astro
|
||||
```
|
||||
|
||||
This page is used any time an error occurs in the dev server.
|
||||
|
||||
The 500 page will receive an `error` query parameter which you can access with:
|
||||
|
||||
```
|
||||
---
|
||||
const error = Astro.request.url.searchParams.get('error');
|
||||
---
|
||||
|
||||
<strong>{error}</strong>
|
||||
```
|
||||
|
||||
A default error page is included with Astro so you will get pretty error messages even without adding a custom 500 page.
|
8
docs/examples.md
Normal file
8
docs/examples.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Examples
|
||||
---
|
||||
|
||||
If you prefer to learn by example, check out our [Examples Library](https://github.com/snowpackjs/astro/tree/main/examples) on GitHub.
|
||||
|
||||
<!-- Once we merge astro-docs back into the main repo, we can actually fetch the list of examples at build-time by scanning the examples/ directory! -->
|
25
docs/guides/data-fetching.md
Normal file
25
docs/guides/data-fetching.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Data Fetching
|
||||
---
|
||||
|
||||
Astro support `fetch()` and "top-level await" to help you do remote data fetching inside of your page. See the ["Data Loading" Pages section](/docs/core-concepts/astro-pages.md#data-loading) for more info.
|
||||
|
||||
**Important:** These are not yet available inside of non-page Astro components. Instead, do all of your data loading inside of your pages, and then pass them to your components as props.
|
||||
|
||||
## Example
|
||||
```astro
|
||||
// Example: src/pages/foo.astro
|
||||
// top-level `fetch()` and `await` are both supported natively in Astro (pages only).
|
||||
const allPokemonResponse = await fetch(`https://pokeapi.co/api/v2/pokemon?limit=150`);
|
||||
const allPokemonResult = await allPokemonResponse.json();
|
||||
const allPokemon = allPokemonResult.results;
|
||||
---
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Original 150 Pokemon</head>
|
||||
<body>
|
||||
{allPokemon.map((pokemon) => (<h1>{pokemon.name}</h1>))}
|
||||
</body>
|
||||
</html>
|
||||
```
|
241
docs/guides/deploy.md
Normal file
241
docs/guides/deploy.md
Normal file
|
@ -0,0 +1,241 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Deploy Your Website
|
||||
---
|
||||
|
||||
> This page is based off of [Vite's](https://vitejs.dev/) well-documented [static deploy instructions](https://vitejs.dev/guide/static-deploy.html).
|
||||
|
||||
The following guides are based on some shared assumptions:
|
||||
|
||||
- You are using the default build output location (`dist/`). This location [can be changed using the `dist` configuration option](/docs/reference/configuration-reference.md).
|
||||
- You are using npm. You can use equivalent commands to run the scripts if you are using Yarn or other package managers.
|
||||
- Astro is installed as a local dev dependency in your project, and you have setup the following npm scripts:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"build": "astro build",
|
||||
"preview": "astro preview"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Building The App
|
||||
|
||||
You may run `npm run build` command to build the app.
|
||||
|
||||
```bash
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
By default, the build output will be placed at `dist/`. You may deploy this `dist/` folder to any of your preferred platforms.
|
||||
|
||||
## GitHub Pages
|
||||
|
||||
1. Set the correct `buildOptions.site` in `astro.config.js`.
|
||||
2. Inside your project, create `deploy.sh` with the following content (with highlighted lines uncommented appropriately), and run it to deploy:
|
||||
|
||||
```bash{13,20,23}
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# abort on errors
|
||||
set -e
|
||||
|
||||
# build
|
||||
npm run build
|
||||
|
||||
# navigate into the build output directory
|
||||
cd dist
|
||||
|
||||
# if you are deploying to a custom domain
|
||||
# echo 'www.example.com' > CNAME
|
||||
|
||||
git init
|
||||
git add -A
|
||||
git commit -m 'deploy'
|
||||
|
||||
# if you are deploying to https://<USERNAME>.github.io
|
||||
# git push -f git@github.com:<USERNAME>/<USERNAME>.github.io.git master
|
||||
|
||||
# if you are deploying to https://<USERNAME>.github.io/<REPO>
|
||||
# git push -f git@github.com:<USERNAME>/<REPO>.git master:gh-pages
|
||||
|
||||
cd -
|
||||
```
|
||||
> You can also run the above script in your CI setup to enable automatic deployment on each push.
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
TODO: We'd love an example action snippet to share here!
|
||||
|
||||
### Travis CI
|
||||
|
||||
1. Set the correct `buildOptions.site` in `astro.config.js`.
|
||||
2. Create a file named `.travis.yml` in the root of your project.
|
||||
3. Run `npm install` locally and commit the generated lockfile (`package-lock.json`).
|
||||
4. Use the GitHub Pages deploy provider template, and follow the [Travis CI documentation](https://docs.travis-ci.com/user/deployment/pages/).
|
||||
|
||||
```yaml
|
||||
language: node_js
|
||||
node_js:
|
||||
- lts/*
|
||||
install:
|
||||
- npm ci
|
||||
script:
|
||||
- npm run build
|
||||
deploy:
|
||||
provider: pages
|
||||
skip_cleanup: true
|
||||
local_dir: dist
|
||||
# A token generated on GitHub allowing Travis to push code on you repository.
|
||||
# Set in the Travis settings page of your repository, as a secure variable.
|
||||
github_token: $GITHUB_TOKEN
|
||||
keep_history: true
|
||||
on:
|
||||
branch: master
|
||||
```
|
||||
|
||||
## GitLab Pages
|
||||
|
||||
1. Set the correct `buildOptions.site` in `astro.config.js`.
|
||||
2. Set `build.outDir` in `astro.config.js` to `public`.
|
||||
3. Create a file called `.gitlab-ci.yml` in the root of your project with the content below. This will build and deploy your site whenever you make changes to your content:
|
||||
|
||||
```yaml
|
||||
image: node:10.22.0
|
||||
pages:
|
||||
cache:
|
||||
paths:
|
||||
- node_modules/
|
||||
script:
|
||||
- npm install
|
||||
- npm run build
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- master
|
||||
```
|
||||
|
||||
## Netlify
|
||||
|
||||
1. On [Netlify](https://netlify.com), setup up a new project from GitHub with the following settings:
|
||||
|
||||
- **Build Command:** `astro build` or `npm run build`
|
||||
- **Publish directory:** `dist`
|
||||
|
||||
2. Hit the deploy button.
|
||||
|
||||
## Google Firebase
|
||||
|
||||
1. Make sure you have [firebase-tools](https://www.npmjs.com/package/firebase-tools) installed.
|
||||
|
||||
2. Create `firebase.json` and `.firebaserc` at the root of your project with the following content:
|
||||
|
||||
`firebase.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"hosting": {
|
||||
"public": "dist",
|
||||
"ignore": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`.firebaserc`:
|
||||
|
||||
```js
|
||||
{
|
||||
"projects": {
|
||||
"default": "<YOUR_FIREBASE_ID>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. After running `npm run build`, deploy using the command `firebase deploy`.
|
||||
|
||||
## Surge
|
||||
|
||||
1. First install [surge](https://www.npmjs.com/package/surge), if you haven’t already.
|
||||
|
||||
2. Run `npm run build`.
|
||||
|
||||
3. Deploy to surge by typing `surge dist`.
|
||||
|
||||
You can also deploy to a [custom domain](http://surge.sh/help/adding-a-custom-domain) by adding `surge dist yourdomain.com`.
|
||||
|
||||
## Heroku
|
||||
|
||||
1. Install [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli).
|
||||
|
||||
2. Create a Heroku account by [signing up](https://signup.heroku.com).
|
||||
|
||||
3. Run `heroku login` and fill in your Heroku credentials:
|
||||
|
||||
```bash
|
||||
$ heroku login
|
||||
```
|
||||
|
||||
4. Create a file called `static.json` in the root of your project with the below content:
|
||||
|
||||
`static.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"root": "./dist"
|
||||
}
|
||||
```
|
||||
|
||||
This is the configuration of your site; read more at [heroku-buildpack-static](https://github.com/heroku/heroku-buildpack-static).
|
||||
|
||||
5. Set up your Heroku git remote:
|
||||
|
||||
```bash
|
||||
# version change
|
||||
$ git init
|
||||
$ git add .
|
||||
$ git commit -m "My site ready for deployment."
|
||||
|
||||
# creates a new app with a specified name
|
||||
$ heroku apps:create example
|
||||
|
||||
# set buildpack for static sites
|
||||
$ heroku buildpacks:set https://github.com/heroku/heroku-buildpack-static.git
|
||||
```
|
||||
|
||||
6. Deploy your site:
|
||||
|
||||
```bash
|
||||
# publish site
|
||||
$ git push heroku master
|
||||
|
||||
# opens a browser to view the Dashboard version of Heroku CI
|
||||
$ heroku open
|
||||
```
|
||||
|
||||
## Vercel
|
||||
|
||||
To deploy your Astro project with a [Vercel for Git](https://vercel.com/docs/git), make sure it has been pushed to a Git repository.
|
||||
|
||||
Go to https://vercel.com/import/git and import the project into Vercel using your Git of choice (GitHub, GitLab or BitBucket). Follow the wizard to select the project root with the project's `package.json` and override the build step using `npm run build` and the output dir to be `./dist`
|
||||
|
||||
After your project has been imported, all subsequent pushes to branches will generate Preview Deployments, and all changes made to the Production Branch (commonly "main") will result in a Production Deployment.
|
||||
|
||||
Once deployed, you will get a URL to see your app live, such as the following: https://astro.vercel.app
|
||||
|
||||
## Azure Static Web Apps
|
||||
|
||||
You can deploy your Astro project with Microsoft Azure [Static Web Apps](https://aka.ms/staticwebapps) service. You need:
|
||||
|
||||
- An Azure account and a subscription key. You can create a [free Azure account here](https://azure.microsoft.com/free).
|
||||
- Your app code pushed to [GitHub](https://github.com).
|
||||
- The [SWA Extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurestaticwebapps) in [Visual Studio Code](https://code.visualstudio.com).
|
||||
|
||||
Install the extension in VS Code and navigate to your app root. Open the Static Web Apps extension, sign in to Azure, and click the '+' sign to create a new Static Web App. You will be prompted to designate which subscription key to use.
|
||||
|
||||
Follow the wizard started by the extension to give your app a name, choose a framework preset, and designate the app root (usually `/`) and built file location `/dist`. The wizard will run and will create a GitHub action in your repo in a `.github` folder.
|
||||
|
||||
The action will work to deploy your app (watch its progress in your repo's Actions tab) and, when successfully completed, you can view your app in the address provided in the extension's progress window by clicking the 'Browse Website' button that appears when the GitHub action has run.
|
139
docs/guides/imports.md
Normal file
139
docs/guides/imports.md
Normal file
|
@ -0,0 +1,139 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Supported Imports
|
||||
---
|
||||
|
||||
Astro uses Snowpack as its internal build system. Snowpack provides Astro with built-in support for the following file types, with no configuration required:
|
||||
|
||||
- JavaScript (`.js`, `.mjs`)
|
||||
- TypeScript (`.ts`, `.tsx`)
|
||||
- JSON (`.json`)
|
||||
- JSX (`.jsx`, `.tsx`)
|
||||
- CSS (`.css`)
|
||||
- CSS Modules (`.module.css`)
|
||||
- Images & Assets (`.svg`, `.jpg`, `.png`, etc.)
|
||||
- Astro Components (`.astro`)
|
||||
- Markdown (`.md`)
|
||||
- WASM (`.wasm`)
|
||||
|
||||
Any files in your `public/` directory are copied into the final build, untouched by Snowpack or Astro. The following applies to files in your `src/` directory, which Astro is ultimately responsible for.
|
||||
|
||||
## JavaScript & ESM
|
||||
|
||||
Astro was designed for JavaScript's native ES Module (ESM) syntax. ESM lets you define explicit imports & exports that browsers and build tools can better understand and optimize for. If you're familiar with the `import` and `export` keywords in JavaScript, then you already know ESM!
|
||||
|
||||
```js
|
||||
// ESM Example - src/user.js
|
||||
export function getUser() {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
// src/index.js
|
||||
import {getUser} from './user.js';
|
||||
```
|
||||
|
||||
All browsers now support ESM, so Astro is able to ship this code directly to the browser during development.
|
||||
|
||||
## TypeScript
|
||||
|
||||
Astro includes built-in support to build TypeScript files (`*.ts`) to JavaScript. Astro components also support TypeScript in the frontmatter script section.
|
||||
|
||||
Note that this built-in support is build only. By default, Astro does not type-check your TypeScript code.
|
||||
|
||||
<!-- To integrate type checking into your development/build workflow, add the [@snowpack/plugin-typescript](https://www.npmjs.com/package/@snowpack/plugin-typescript) plugin. -->
|
||||
|
||||
## JSX
|
||||
|
||||
Astro includes built-in support to build JSX files (`*.jsx` & `*.tsx`) to JavaScript.
|
||||
|
||||
If you are using Preact, Astro will detect your Preact import and switch to use the Preact-style JSX `h()` function. This is all done automatically for you.
|
||||
|
||||
**Note: Astro does not support JSX in `.js`/`.ts` files.**
|
||||
|
||||
## JSON
|
||||
|
||||
```js
|
||||
// Load the JSON object via the default export
|
||||
import json from './data.json';
|
||||
```
|
||||
|
||||
Astro supports importing JSON files directly into your application. Imported files return the full JSON object in the default import.
|
||||
|
||||
## CSS
|
||||
|
||||
```js
|
||||
// Load and inject 'style.css' onto the page
|
||||
import './style.css';
|
||||
```
|
||||
|
||||
Astro supports importing CSS files directly into your application. Imported styles expose no exports, but importing one will automatically add those styles to the page. This works for all CSS files by default, and can support compile-to-CSS languages like Sass & Less via plugins.
|
||||
|
||||
If you prefer not to write CSS, Astro also supports all popular CSS-in-JS libraries (ex: styled-components) for styling.
|
||||
|
||||
## CSS Modules
|
||||
|
||||
```js
|
||||
// 1. Converts './style.module.css' classnames to unique, scoped values.
|
||||
// 2. Returns an object mapping the original classnames to their final, scoped value.
|
||||
import styles from './style.module.css';
|
||||
|
||||
// This example uses JSX, but you can use CSS Modules with any framework.
|
||||
return <div className={styles.error}>Your Error Message</div>;
|
||||
```
|
||||
|
||||
Astro supports CSS Modules using the `[name].module.css` naming convention. Like any CSS file, importing one will automatically apply that CSS to the page. However, CSS Modules export a special default `styles` object that maps your original classnames to unique identifiers.
|
||||
|
||||
CSS Modules help you enforce component scoping & isolation on the frontend with unique-generated class names for your stylesheets.
|
||||
|
||||
## Other Assets
|
||||
|
||||
```jsx
|
||||
import imgReference from './image.png'; // img === '/src/image.png'
|
||||
import svgReference from './image.svg'; // svg === '/src/image.svg'
|
||||
import txtReference from './words.txt'; // txt === '/src/words.txt'
|
||||
|
||||
// This example uses JSX, but you can use import references with any framework.
|
||||
<img src={imgReference} />;
|
||||
```
|
||||
|
||||
All other assets not explicitly mentioned above can be imported via ESM `import` and will return a URL reference to the final built asset. This can be useful for referencing non-JS assets by URL, like creating an image element with a `src` attribute pointing to that image.
|
||||
|
||||
## WASM
|
||||
|
||||
```js
|
||||
// Loads and intializes the requested WASM file
|
||||
const wasm = await WebAssembly.instantiateStreaming(fetch('/example.wasm'));
|
||||
```
|
||||
|
||||
Astro supports loading WASM files directly into your application using the browser's [`WebAssembly`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) API. Read our [WASM guide](/docs/guides/wasm.md) to learn more.
|
||||
|
||||
## NPM Packages
|
||||
|
||||
```js
|
||||
// Returns the React & React-DOM npm packages
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
```
|
||||
|
||||
Astro lets you import npm packages directly in the browser. Even if a package was published using a legacy format, Astro will up-convert the package to ESM before serving it to the browser.
|
||||
|
||||
When you start up your dev server or run a new build, you may see a message that Snowpack is "installing dependencies". This means that Snowpack is converting your dependencies to run in the browser. This needs to run only once, or until you next change your dependency tree by adding or removing dependencies.
|
||||
|
||||
## Node Builtins
|
||||
|
||||
We encourage Astro users to avoid Node.js builtins (`fs`, `path`, etc) whenever possible. Astro aims to be compatible with multiple JavaScript runtimes in the future. This includes [Deno](https://deno.land/) and [Cloudflare Workers](https://workers.cloudflare.com/) which do not support Node builtin modules such as `fs`.
|
||||
|
||||
Our aim is to provide Astro alternatives to common Node.js builtins. However, no such alternatives exist today. So, if you _really_ need to use these builtin modules we don't want to stop you. Astro supports Node.js builtins using Node's newer `node:` prefix. If you want to read a file, for example, you can do so like this:
|
||||
|
||||
```jsx
|
||||
---
|
||||
// Example: import the "fs/promises" builtin from Node.js
|
||||
import fs from 'node:fs/promises';
|
||||
|
||||
const url = new URL('../../package.json', import.meta.url);
|
||||
const json = await fs.readFile(url, 'utf-8');
|
||||
const data = JSON.parse(json);
|
||||
---
|
||||
|
||||
<span>Version: {data.version}</span>
|
||||
```
|
|
@ -1,33 +1,54 @@
|
|||
## ✍️ Markdown
|
||||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Markdown Content
|
||||
---
|
||||
|
||||
Astro comes with out-of-the-box Markdown support powered by the expansive [**remark**](https://github.com/remarkjs/remark) ecosystem.
|
||||
Astro comes with out-of-the-box Markdown support powered by the expansive [remark](https://remark.js.org/) ecosystem.
|
||||
|
||||
## Remark Plugins
|
||||
### Remark Plugins
|
||||
|
||||
**This is the first draft of Markdown support!** While we plan to support user-provided `remark` plugins soon, our hope is that you won't need `remark` plugins at all!
|
||||
|
||||
In addition to [custom components inside the `<Markdown>` component](#markdown-component), Astro comes with [GitHub-flavored Markdown](https://github.github.com/gfm/) support, [Footnotes](https://github.com/remarkjs/remark-footnotes) syntax, [Smartypants](https://github.com/silvenon/remark-smartypants), and syntax highlighting via [Prism](https://prismjs.com/) pre-enabled. These features are likely to be configurable in the future.
|
||||
In addition to [custom components inside the `<Markdown>` component](https://github.com/snowpackjs/astro/blob/main/docs/markdown.md#markdown-component), Astro comes with [Github-flavored Markdown](https://github.github.com/gfm/) support, [Footnotes](https://github.com/remarkjs/remark-footnotes) syntax, [Smartypants](https://github.com/silvenon/remark-smartypants), and syntax highlighting via [Prism](https://prismjs.com/) pre-enabled. These features are likely to be configurable in the future.
|
||||
|
||||
### Markdown Pages
|
||||
|
||||
Astro treats any `.md` files inside of the `/src/pages` directory as pages. These pages are processed as plain Markdown files and do not support components. If you're looking to embed rich components in your Markdown, take a look at the [Markdown Component](#markdown-component) section.
|
||||
Astro treats any `.md` files inside of the `/src/pages` directory as pages. These pages are processed as plain markdown files and do not support components. If you're looking to embed rich components in your markdown, take a look at the [Markdown Component](#astros-markdown-component) section.
|
||||
|
||||
#### `layout`
|
||||
`layout`
|
||||
|
||||
The only special Frontmatter key is `layout`, which defines the relative path to a `.astro` component which should wrap your Markdown content.
|
||||
The only special Frontmatter key is `layout`, which defines the relative path to an `.astro` component which should wrap your Markdown content.
|
||||
|
||||
`src/pages/index.md`
|
||||
|
||||
```md
|
||||
```jsx
|
||||
---
|
||||
layout: ../layouts/main.astro
|
||||
---
|
||||
|
||||
# Hello world!
|
||||
# Hello World!
|
||||
```
|
||||
|
||||
Layout files are normal `.astro` components. Any Frontmatter defined in your `.md` page will be exposed to the Layout component as the `content` prop. `content` also has an `astro` key which holds special metadata about your file, like the complete Markdown `source` and a `headings` object.
|
||||
|
||||
Keep in mind that the only guaranteed variables coming from the `content` prop object are `astro` and `url`. An example of what a blog post `content` object might look like is as follows:
|
||||
|
||||
```json
|
||||
{
|
||||
/** Frontmatter from blog post
|
||||
"title": "",
|
||||
"date": "",
|
||||
"author": "",
|
||||
"description": "",
|
||||
**/
|
||||
"astro": {
|
||||
"headers": [],
|
||||
"source": ""
|
||||
},
|
||||
"url": ""
|
||||
}
|
||||
```
|
||||
|
||||
The rendered Markdown content is placed into the default `<slot />` element.
|
||||
|
||||
`src/layouts/main.astro`
|
||||
|
@ -48,11 +69,33 @@ const { content } = Astro.props;
|
|||
</html>
|
||||
```
|
||||
|
||||
### Markdown Component
|
||||
### Astro's Markdown Component
|
||||
|
||||
Similar to tools like [MDX](https://mdxjs.com/) or [MDsveX](https://github.com/pngwn/MDsveX), Astro makes it straightforward to embed rich, interactive components inside of your Markdown content. The `<Markdown>` component is statically rendered, so it does not add any runtime overhead.
|
||||
Astro has a dedicated component used to let you render your markdown as HTML components. This is a special component that is only exposed to `.astro` files. To use the `<Markdown>` component, within yout frontmatter block use the following import statement:
|
||||
|
||||
Astro exposes a special `Markdown` component for `.astro` files which enables markdown syntax for its children **recursively**. Within the `Markdown` component you may also use plain HTML or any other type of component that is supported by Astro.
|
||||
```jsx
|
||||
---
|
||||
import { Markdown } from 'astro/components';
|
||||
---
|
||||
```
|
||||
|
||||
You can utilize this within your `.astro` file by doing the following:
|
||||
|
||||
```jsx
|
||||
---
|
||||
import { Markdown } from 'astro/components';
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<Markdown>
|
||||
# Hello world!
|
||||
|
||||
The contents inside here is all in markdown.
|
||||
</Markdown>
|
||||
</Layout>
|
||||
```
|
||||
|
||||
`<Markdown>` components provide more flexibility and allow you to use plain HTML or custom components. For example:
|
||||
|
||||
````jsx
|
||||
---
|
||||
|
@ -97,7 +140,7 @@ const expressions = 'Lorem ipsum';
|
|||
|
||||
### Remote Markdown
|
||||
|
||||
If you have Markdown in a remote source, you may pass it directly to the Markdown component through the `content` attribute. For example, the example below fetches the README from Snowpack's GitHub repository and renders it as HTML.
|
||||
If you have Markdown in a remote source, you may pass it directly to the Markdown component through the `content` attribute. For example, the example below fetches the README from Snowpack's Github repository and renders it as HTML.
|
||||
|
||||
```jsx
|
||||
---
|
||||
|
@ -111,7 +154,7 @@ const content = await fetch('https://raw.githubusercontent.com/snowpackjs/snowpa
|
|||
</Layout>
|
||||
```
|
||||
|
||||
Some times you might want to combine dynamic markdown with static markdown. You can nest `Markdown` components to get the best of both worlds.
|
||||
There might be times when you want to combine both dynamic, and static markdown. If that is the case, you can nest `<Markdown>` components with each other to get the best of both worlds.
|
||||
|
||||
```jsx
|
||||
---
|
||||
|
@ -135,8 +178,8 @@ const content = await fetch('https://raw.githubusercontent.com/snowpackjs/snowpa
|
|||
|
||||
**Aren't there security concerns to rendering remote markdown directly to HTML?**
|
||||
|
||||
Yes! Just like with regular HTML, improper use the `<Markdown>` component can open you up to a [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) attack. If you are rendering untrusted content, be sure to _santize your content **before** rendering it_.
|
||||
Yes! Just like with regular HTML, improper use of the `Markdown` component can open you up to a [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) attack. If you are rendering untrusted content, be sure to _sanitize your content **before** rendering it_.
|
||||
|
||||
**Why not use a prop like React's `dangerouslySetInnerHTML={{ __html: content }}`?**
|
||||
|
||||
Rendering a string of HTML (or Markdown) is an extremely common use case when rendering a static site and you probably don't need the extra hoops to jump through. Rendering untrusted content is always dangerous! Be sure to _santize your content **before** rendering it_.
|
||||
Rendering a string of HTML (or Markdown) is an extremely common use case when rendering a static site and you probably don't need the extra hoops to jump through. Rendering untrusted content is always dangerous! Be sure to _sanitize your content **before** rendering it_.
|
83
docs/guides/publish-to-npm.md
Normal file
83
docs/guides/publish-to-npm.md
Normal file
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Publish Components to NPM
|
||||
---
|
||||
|
||||
Built a great Astro component? **Publish it to [npm!](https://npmjs.com/)**
|
||||
|
||||
Once published to npm, Astro components can be installed and used in your project like any other npm package. npm is a great way to share Astro components across projects within your team, your company, or the entire world.
|
||||
|
||||
## Basic NPM Package Setup
|
||||
|
||||
Here's an example package that we'd like to publish to npm. It includes two Astro components and a few other files.
|
||||
|
||||
```
|
||||
/my-components-package/
|
||||
├── package.json
|
||||
├── index.js
|
||||
├── Capitalize.astro
|
||||
└── Bold.astro
|
||||
```
|
||||
|
||||
### `package.json`
|
||||
|
||||
Your package manifest. This includes information about your package such as name, description, any dependencies, and other important metadata. If you don't know what the `package.json` file is, we highly recommend you to have a quick read on [the npm documentation](https://docs.npmjs.com/creating-a-package-json-file).
|
||||
|
||||
We recommend that you define an [exports entry](https://nodejs.org/api/packages.html) for your `index.js` package entrypoint like so:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "@example/my-components",
|
||||
"version": "0.0.1",
|
||||
"exports": "./index.js"
|
||||
}
|
||||
```
|
||||
|
||||
### `index.js`
|
||||
|
||||
`index.js` is your package entrypoint, which is the file that gets loaded when someone imports your package by name. Having a JavaScript file as your package entrypoint will let you export multiple components and have better control over their exported component names.
|
||||
|
||||
```js
|
||||
export { default as Capitalize } from './Capitalize.astro';
|
||||
export { default as Bold } from './Bold.astro';
|
||||
```
|
||||
|
||||
### Publishing
|
||||
|
||||
Once you have your package ready, you can publish it to npm by running the command `npm publish`. If that fails, make sure that you've logged in via `npm login` and that your package.json is correct.
|
||||
|
||||
Once published, anyone will be able to install your components and then import them like so:
|
||||
|
||||
```astro
|
||||
---
|
||||
import { Bold, Capitalize } from '@example/my-components';
|
||||
---
|
||||
<Capitalize phrase={`Hello world`} />
|
||||
```
|
||||
|
||||
## Advanced
|
||||
|
||||
We recommend a single `index.js` package entrypoint because this is what most users are familar with. However, in some rare scenarios you may want to have your users import each `.astro` component directly, in the same manner that you import `.astro` files in your own project.
|
||||
|
||||
```astro
|
||||
---
|
||||
import Capitalize from '@example/my-components/Capitalize.astro';
|
||||
---
|
||||
<Capitalize phrase={`Hello world`} />
|
||||
```
|
||||
|
||||
This is a less common scenario, and we only recommend it if you have good reason. Because Astro is completely rendered at build-time, there are no client-side performance concerns to our default recommendation to export your components from a single `index.js` file.
|
||||
|
||||
To support importing by file within your package, add each file to your **package.json** `exports` map:
|
||||
|
||||
```diff
|
||||
{
|
||||
"name": "@example/my-components",
|
||||
"version": "1.0.0",
|
||||
"exports": {
|
||||
- ".": "./index.js",
|
||||
+ "./Bold.astro": "./Bold.astro",
|
||||
+ "./Capitalize.astro": "./Capitalize.astro"
|
||||
}
|
||||
}
|
||||
```
|
|
@ -1,17 +1,7 @@
|
|||
# 💅 Styling
|
||||
|
||||
Styling in Astro is meant to be as flexible as you’d like it to be! The following options are all supported:
|
||||
|
||||
| Framework | Global CSS | Scoped CSS | CSS Modules |
|
||||
| :--------------- | :--------: | :--------: | :---------: |
|
||||
| `.astro` | ✅ | ✅ | N/A¹ |
|
||||
| `.jsx` \| `.tsx` | ✅ | ❌ | ✅ |
|
||||
| `.vue` | ✅ | ✅ | ✅ |
|
||||
| `.svelte` | ✅ | ✅ | ❌ |
|
||||
|
||||
¹ _`.astro` files have no runtime, therefore Scoped CSS takes the place of CSS Modules (styles are still scoped to components, but don’t need dynamic values)_
|
||||
|
||||
All styles in Astro are automatically [**autoprefixed**](#-autoprefixer) and optimized, so you can just write CSS and we’ll handle the rest ✨.
|
||||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Styling
|
||||
---
|
||||
|
||||
## 🖍 Quick Start
|
||||
|
||||
|
@ -47,6 +37,31 @@ Styling in an Astro component is done by adding a `<style>` tag anywhere. By def
|
|||
- For best result, only have one `<style>` tag per-Astro component. This isn’t necessarily a limitation, but it may result in better optimization at buildtime.
|
||||
- If you want to import third-party libraries into an Astro component, you can use [Sass][sass]! In particular, [@use][sass-use] may come in handy (e.g. `@use "bootstrap/scss/bootstrap"`);
|
||||
|
||||
## Cross-Browser Compatibility
|
||||
|
||||
We also automatically add browser prefixes using [Autoprefixer][autoprefixer]. By default, Astro loads the [Browserslist defaults][browserslist-defaults], but you may also specify your own by placing a [Browserslist][browserslist] file in your project root.
|
||||
|
||||
---
|
||||
|
||||
## Supported Styling Options
|
||||
|
||||
Styling in Astro is meant to be as flexible as you’d like it to be! The following options are all supported:
|
||||
|
||||
| Framework | Global CSS | Scoped CSS | CSS Modules |
|
||||
| :--------------- | :--------: | :--------: | :---------: |
|
||||
| `.astro` | ✅ | ✅ | N/A¹ |
|
||||
| `.jsx` \| `.tsx` | ✅ | ❌ | ✅ |
|
||||
| `.vue` | ✅ | ✅ | ✅ |
|
||||
| `.svelte` | ✅ | ✅ | ❌ |
|
||||
|
||||
¹ _`.astro` files have no runtime, therefore Scoped CSS takes the place of CSS Modules (styles are still scoped to components, but don’t need dynamic values)_
|
||||
|
||||
All styles in Astro are automatically [**autoprefixed**](#cross-browser-compatibility) and optimized, so you can just write CSS and we’ll handle the rest ✨.
|
||||
|
||||
---
|
||||
|
||||
## Using Frameworks and Libraries
|
||||
|
||||
### 📘 React / Preact
|
||||
|
||||
`.jsx` files support both global CSS and CSS Modules. To enable the latter, use the `.module.css` extension (or `.module.scss`/`.module.sass` if using Sass).
|
||||
|
@ -78,10 +93,6 @@ Astro also supports [Sass][sass] out-of-the-box. To enable for each framework:
|
|||
|
||||
💁 Sass is great! If you haven’t used Sass in a while, please give it another try. The new and improved [Sass Modules][sass-use] are a great fit with modern web development, and it’s blazing-fast since being rewritten in Dart. And the best part? **You know it already!** Use `.scss` to write familiar CSS syntax you’re used to, and only sprinkle in Sass features if/when you need them.
|
||||
|
||||
### 🦊 Autoprefixer
|
||||
|
||||
We also automatically add browser prefixes using [Autoprefixer][autoprefixer]. By default, Astro loads the [Browserslist defaults][browserslist-defaults], but you may also specify your own by placing a [Browserslist][browserslist] file in your project root.
|
||||
|
||||
### 🍃 Tailwind
|
||||
|
||||
Astro can be configured to use [Tailwind][tailwind] easily! Install the dependencies:
|
||||
|
@ -96,7 +107,7 @@ And also create a `tailwind.config.js` in your project root:
|
|||
// tailwind.config.js
|
||||
module.exports = {
|
||||
mode: 'jit',
|
||||
purge: ['./public/**/*.html', './src/**/*.{astro,js,jsx,ts,tsx,vue,svelte}'],
|
||||
purge: ['./public/**/*.html', './src/**/*.{astro,js,jsx,ts,tsx,vue}'],
|
||||
// more options here
|
||||
};
|
||||
```
|
||||
|
@ -123,7 +134,9 @@ Now you’re ready to write Tailwind! Our recommended approach is to create a `p
|
|||
|
||||
💁 As an alternative to `public/global.css`, You may also add Tailwind utilities to individual `pages/*.astro` components in `<style>` tags, but be mindful of duplication! If you end up creating multiple Tailwind-managed stylesheets for your site, make sure you’re not sending the same CSS to users over and over again in separate CSS files.
|
||||
|
||||
### 📦 Bundling
|
||||
---
|
||||
|
||||
## 📦 Bundling
|
||||
|
||||
All CSS is minified and bundled automatically for you in running `astro build`. Without getting too in the weeds, the general rules are:
|
||||
|
||||
|
@ -135,6 +148,8 @@ We’ll be expanding our styling optimization story over time, and would love yo
|
|||
|
||||
_Note: be mindful when some page styles get extracted to the ”common” bundle, and some page styles stay on-page. For most people this may not pose an issue, but when part of your styles are bundled they technically may load in a different order and your cascade may be different. While problem isn’t unique to Astro and is present in almost any CSS bundling process, it can be unexpected if you’re not anticipating it. Be sure to inspect your final production build, and please [report any issues][issues] you may come across._
|
||||
|
||||
---
|
||||
|
||||
## 📚 Advanced Styling Architecture in Astro
|
||||
|
||||
Too many development setups take a hands-off approach to CSS, or at most leave you with only contrived examples that don’t get you very far. Telling developers “Use whatever styling solution you want!” is a nice thought that rarely works out in practice. Few styling approaches lend themselves to every setup. Astro is no different—certain styling approaches _will_ work better than others.
|
||||
|
@ -181,8 +196,6 @@ _Note: all the examples here use `lang="scss"` which is a great convenience for
|
|||
|
||||
That `.btn` class is scoped within that component, and won’t leak out. It means that you can **focus on styling and not naming.** Local-first approach fits in very well with Astro’s ESM-powered design, favoring encapsulation and reusability over global scope. While this is a simple example, it should be noted that **this scales incredibly well.** And if you need to share common values between components, [Sass’ module system][sass-use] also gets our recommendation for being easy to use, and a great fit with component-first design.
|
||||
|
||||
---
|
||||
|
||||
By contrast, Astro does allow global styles via the `:global()` escape hatch, however, this should be avoided if possible. To illustrate this: say you used your button in a `<Nav />` component, and you wanted to style it differently there. You might be tempted to have something like:
|
||||
|
||||
```jsx
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
title: Hello, Documentation!
|
||||
layout: ../layouts/Main.astro
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Start Here
|
||||
---
|
||||
|
||||
<img src="https://github.com/snowpackjs/astro/blob/main/assets/social/banner.png?raw=true" alt="Astro" width="638" height="320" >
|
||||
<img src="https://github.com/snowpackjs/astro/blob/main/assets/social/banner.png?raw=true" alt="Astro" width="100%" height="auto" >
|
||||
|
||||
## What is Astro?
|
||||
|
||||
|
@ -17,7 +17,7 @@ With Astro, you can use your favorite JavaScript framework and automatically shi
|
|||
|
||||
## 🔧 Quick Start
|
||||
|
||||
> **Important**: Astro is built with [ESM modules](https://nodejs.org/api/esm.html) which are not supported in older version of Node.js. The minimum supported version is **14.16.1**.
|
||||
> __Important__: Astro is built with [ESM modules](https://nodejs.org/api/esm.html) which are not supported in older version of Node.js. The minimum supported version is __14.16.1__.
|
||||
|
||||
```bash
|
||||
# create your project
|
93
docs/installation.md
Normal file
93
docs/installation.md
Normal file
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Installation
|
||||
---
|
||||
|
||||
There are a few different ways to install
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Node.js** - `v12.20.0`, `v14.13.1`, `v16.0.0`, or higher.
|
||||
- **A text editor** - We recommend [VS Code](https://code.visualstudio.com/) with the [Astro extension](https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode).
|
||||
- **A terminal** - Astro is mainly accessed by terminal command-line.
|
||||
|
||||
## Recommended Install
|
||||
|
||||
`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 walk you through setting up a new project.
|
||||
|
||||
```bash
|
||||
mkdir <project-name>
|
||||
cd <project-name>
|
||||
npm init astro
|
||||
```
|
||||
|
||||
Follow the CLI instructions to install Astro with one of our official project starter templates.
|
||||
|
||||
Once completed, jump over to our [Quickstart Guide](/docs/quick-start.md#start-your-project) for a 30-second walkthrough on how to start & build your new Astro project!
|
||||
|
||||
## Manual Install
|
||||
|
||||
### Set up your project
|
||||
|
||||
Create an empty directory with the name of your project, and then navigate into it:
|
||||
|
||||
```bash
|
||||
mkdir <project-name>
|
||||
cd <project-name>
|
||||
# Note: Replace <project-name> with the name of your project.
|
||||
```
|
||||
|
||||
Create a new `package.json` file for your project. Astro is designed to work with the npm ecosystem of packages, which is managed in a `package.json` project manifest. If you don't know what the `package.json` file is, we highly recommend you to have a quick read on [the npm documentation](https://docs.npmjs.com/creating-a-package-json-file).
|
||||
|
||||
```bash
|
||||
# This command will create a basic package.json for you
|
||||
npm init --yes
|
||||
```
|
||||
|
||||
### Install Astro
|
||||
|
||||
If you've followed the instructions above, you should have a directory with a single `package.json` file inside of it. You can now install Astro in your project.
|
||||
|
||||
We'll use `npm` in the examples below, but you could also use `yarn` or `pnpm` if you prefer an npm alternative. If you aren't familiar with `yarn` or `pnpm`, then we strongly recommend sticking with `npm`.
|
||||
|
||||
```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"
|
||||
+ "start": "astro dev",
|
||||
+ "build": "astro build",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Create your first page
|
||||
|
||||
Open up your favorite text editor, and create a new file in your project:
|
||||
|
||||
```astro
|
||||
---
|
||||
// 1. Create a new file at <project-directory>/src/pages/index.astro
|
||||
// 2. Copy-and-paste this entire file (including `-` dashes) into it.
|
||||
---
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello, World!</h1>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
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, you can create a new file at `src/pages/about.astro` (reusing the previous snippet) and Astro will generate a new page at the `/about` URL.
|
||||
|
||||
### Next Steps
|
||||
|
||||
Success! You're now ready to start developing! Jump over to our [Quickstart Guide](/docs/quick-start.md#start-your-project) for a 30-second walkthrough on how to start & build your new Astro project!
|
||||
|
||||
📚 Learn more about Astro's project structure in our [Project Structure guide](/docs/core-concepts/project-structure.md).
|
||||
📚 Learn more about Astro's component syntax in our [Astro Components guide](/docs/core-concepts/astro-components.md).
|
||||
📚 Learn more about Astro's file-based routing in our [Routing guide](core-concepts/astro-pages).
|
||||
|
4
docs/integrations/data-sources-cms.md
Normal file
4
docs/integrations/data-sources-cms.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Data Sources / CMS
|
||||
---
|
4
docs/integrations/deploy-astro.md
Normal file
4
docs/integrations/deploy-astro.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Deploy Astro
|
||||
---
|
4
docs/integrations/developer-tools.md
Normal file
4
docs/integrations/developer-tools.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Developer Tools
|
||||
---
|
4
docs/integrations/state-management.md
Normal file
4
docs/integrations/state-management.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: State Management
|
||||
---
|
4
docs/integrations/styles-and-css-libraries.md
Normal file
4
docs/integrations/styles-and-css-libraries.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Styles & CSS Libraries
|
||||
---
|
|
@ -1,94 +0,0 @@
|
|||
# Publishing Astro components
|
||||
|
||||
Astro is able to use components from most popular frameworks such as React, Vue, Svelte and Preact out of the box. You can also write components in the `.astro` format.
|
||||
|
||||
Every framework recommends different methods for publishing components, this document talks about how we suggest you publish Astro components to [npm](https://www.npmjs.com/).
|
||||
|
||||
## Astro component use cases
|
||||
|
||||
Astro components are server-only and provide a lightweight HTML-like syntax.
|
||||
|
||||
This makes Astro components a good match for anything that doesn't need to be interactive in the client. Astro comes with a few built-in components such as the [Prism](https://prismjs.com/) component which you can use like so:
|
||||
|
||||
```jsx
|
||||
---
|
||||
import { Prism } from 'astro/components';
|
||||
---
|
||||
|
||||
<Prism code={`const foo = 'bar';`} />
|
||||
```
|
||||
|
||||
This component provides syntax highlighting for code blocks. Since this never changes in the client it makes sense to use an Astro component (it's equally reasonable to use a framework component for this kind of thing; Astro is server-only by default for all frameworks!).
|
||||
|
||||
## Publishing components
|
||||
|
||||
Some frameworks, such as [React](https://reactjs.org/) recommend pre-compiling components to JavaScript and publishing the artifacts. Astro currently doesn't have a way to pre-compile components, so we recommend publishing the `.astro` files directly.
|
||||
|
||||
Here's an example project with a couple of components.
|
||||
|
||||
```
|
||||
/my-components/
|
||||
├── package.json
|
||||
├── index.js
|
||||
├── capitalize.astro
|
||||
└── bold.astro
|
||||
```
|
||||
|
||||
Where **index.js** looks like this:
|
||||
|
||||
```js
|
||||
export { default as Capitalize } from './capitalize.astro';
|
||||
export { default as Bold } from './bold.astro';
|
||||
```
|
||||
|
||||
In your **package.json** define an [exports entry](https://nodejs.org/api/packages.html) like so:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "@example/my-components",
|
||||
"version": "1.0.0",
|
||||
"exports": "./index.js"
|
||||
}
|
||||
```
|
||||
|
||||
This will allow consumers to import your components like so:
|
||||
|
||||
```svelte
|
||||
---
|
||||
import { Bold, Capitalize } from '@example/my-components';
|
||||
---
|
||||
|
||||
<Capitalize phrase={`Hello world`} />
|
||||
```
|
||||
|
||||
### Importing astro components directly
|
||||
|
||||
Above we created an index file that re-exports our components, which gives us the ability to publish several components in a single package. Since Astro components are server only we don't need to worry about tree-shaking concerns.
|
||||
|
||||
However you can also import published `.astro` files directly, in the same manner that you import `.astro` files in your own project.
|
||||
|
||||
Change the above **package.json** to this:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "@example/my-components",
|
||||
"version": "1.0.0",
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./bold.astro": "./bold.astro",
|
||||
"./capitalize.astro": "./capitalize.astro"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `"."` is used to signify the package's main module. We set it to the **index.js** file to allow the import method shown above.
|
||||
|
||||
Adding `"./bold.astro"` and `"./capitalize.astro"` to the exports field also allows consumers to import the components directly, by file name, like so:
|
||||
|
||||
```svelte
|
||||
---
|
||||
import Capitalize from '@example/my-components/capitalize.astro';
|
||||
---
|
||||
|
||||
<Capitalize phrase={`Hello world`} />
|
||||
```
|
51
docs/quick-start.md
Normal file
51
docs/quick-start.md
Normal file
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Quick Start
|
||||
---
|
||||
|
||||
```shell
|
||||
# prerequisite: check that Node.js is 12.20.0+, 14.13.1+, or 16+
|
||||
node --version
|
||||
|
||||
# create a new project directory, and `cd` into it
|
||||
mkdir mkdirtest && cd "$_"
|
||||
|
||||
# prepare for liftoff...
|
||||
npm init astro
|
||||
|
||||
# install dependencies
|
||||
npm install
|
||||
|
||||
# start developing!
|
||||
npm run start
|
||||
|
||||
# when you're ready: build your static site to `dist/`
|
||||
npm run build
|
||||
```
|
||||
|
||||
To deploy your Astro site to production, upload the contents of the `/dist` folder (generated by running `npm run build`) to your favorite hosting provider.
|
||||
|
||||
|
||||
|
||||
## Start your project
|
||||
|
||||
Go back to your command-line terminal, and run the following command in your project directory:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
Your application is now running on [http://localhost:3000](http://localhost:3000). Open this URL in your browser and you should see the text "Hello, World" that we copied in the previous step.
|
||||
|
||||
Astro will listen for file changes in your `src/` directory, so you do not need to restart the application as you make changes during development.
|
||||
|
||||
|
||||
## Build your project
|
||||
|
||||
Go back to your command-line terminal, and run the following command in your project directory:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
This will build your site and write it to disk in the `dist/` directory. Astro sites are static, so they can be deployed to your favorite host (Vercel, Netlify, an S3 bucket, etc.).
|
|
@ -1,10 +1,13 @@
|
|||
## 📚 API
|
||||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: API Reference
|
||||
---
|
||||
|
||||
### `Astro` global
|
||||
## `Astro` global
|
||||
|
||||
The `Astro` global is available in all contexts in `.astro` files. It has the following functions:
|
||||
|
||||
#### `fetchContent()`
|
||||
### `Astro.fetchContent()`
|
||||
|
||||
`Astro.fetchContent()` is a way to load local `*.md` files into your static site setup. You can either use this on its own, or within [Astro Collections][docs-collections].
|
||||
|
||||
|
@ -45,7 +48,7 @@ const data = Astro.fetchContent('../pages/post/*.md'); // returns an array of po
|
|||
}[]
|
||||
```
|
||||
|
||||
#### `request`
|
||||
### `Astro.request`
|
||||
|
||||
`Astro.request` returns an object with the following properties:
|
||||
|
||||
|
@ -56,11 +59,12 @@ const data = Astro.fetchContent('../pages/post/*.md'); // returns an array of po
|
|||
|
||||
⚠️ Temporary restriction: this is only accessible in top-level pages and not in sub-components.
|
||||
|
||||
#### `site`
|
||||
### `Astro.site`
|
||||
|
||||
`Astro.site` returns a `URL` made from `buildOptions.site` in your Astro config. If undefined, this will return a URL generated from `localhost`.
|
||||
|
||||
### `collection`
|
||||
## Collections API
|
||||
### `collection` prop
|
||||
|
||||
```jsx
|
||||
const { collection } = Astro.props;
|
||||
|
@ -111,7 +115,7 @@ _\* Note: don’t create confusing URLs with `permalink`, e.g. rearranging param
|
|||
|
||||
⚠️ `createCollection()` executes in its own isolated scope before page loads. Therefore you can’t reference anything from its parent scope. If you need to load data you may fetch or use async `import()`s within the function body for anything you need (that’s why it’s `async`—to give you this ability). If it wasn’t isolated, then `collection` would be undefined! Therefore, duplicating imports between `createCollection()` and your Astro component is OK.
|
||||
|
||||
#### 📡 RSS Feed
|
||||
#### RSS Feed
|
||||
|
||||
You can optionally generate an RSS 2.0 feed from `createCollection()` by adding an `rss` option. Here are all the options:
|
||||
|
||||
|
@ -156,7 +160,7 @@ Astro will generate an RSS 2.0 feed at `/feed/[collection].xml` (for example, `/
|
|||
<link rel="alternate" type="application/rss+xml" title="My RSS Feed" href="/feed/podcast.xml" />
|
||||
```
|
||||
|
||||
### `import.meta`
|
||||
## `import.meta`
|
||||
|
||||
All ESM modules include a `import.meta` property. Astro adds `import.meta.env` through [Snowpack](https://www.snowpack.dev/).
|
||||
|
||||
|
@ -175,22 +179,3 @@ export default function () {
|
|||
[docs-collections]: ./collections.md
|
||||
[rss]: #-rss-feed
|
||||
|
||||
### Node builtins
|
||||
|
||||
Astro aims to be compatible with multiple JavaScript runtimes in the future. This includes [Deno](https://deno.land/) and [Cloudflare Workers](https://workers.cloudflare.com/) which do not support Node builtin modules such as `fs`. We encourage Astro users to write their code as cross-environment as possible.
|
||||
|
||||
Due to that, you cannot use Node modules that you're familiar with such as `fs` and `path`. Our aim is to provide alternative built in to Astro. If you're use case is not covered please let us know.
|
||||
|
||||
However, if you _really_ need to use these builtin modules we don't want to stop you. Node supports the `node:` prefix for importing builtins, and this is also supported by Astro. If you want to read a file, for example, you can do so like this:
|
||||
|
||||
```jsx
|
||||
---
|
||||
import fs from 'node:fs/promises';
|
||||
|
||||
const url = new URL('../../package.json', import.meta.url);
|
||||
const json = await fs.readFile(url, 'utf-8');
|
||||
const data = JSON.parse(json);
|
||||
---
|
||||
|
||||
<span>Version: {data.version}</span>
|
||||
```
|
32
docs/reference/builtin-components.md
Normal file
32
docs/reference/builtin-components.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Astro Builtin Components
|
||||
---
|
||||
|
||||
Astro includes several builtin components for you to use in your projects. All builtin components are available via `import {} from 'astro/components';`.
|
||||
|
||||
## `<Markdown />`
|
||||
|
||||
```astro
|
||||
---
|
||||
import { Markdown } from 'astro/components';
|
||||
---
|
||||
<Markdown>
|
||||
# Markdown syntax is now supported! **Yay!**
|
||||
</Markdown>
|
||||
```
|
||||
|
||||
See our [Markdown Guide](/docs/guides/markdown-content.md) for more info.
|
||||
<!-- TODO: We should move some of the specific component info here. -->
|
||||
|
||||
|
||||
## `<Prism />`
|
||||
|
||||
```astro
|
||||
---
|
||||
import { Prism } from 'astro/components';
|
||||
---
|
||||
<Prism code={`const foo = 'bar';`} />
|
||||
```
|
||||
|
||||
This component provides syntax highlighting for code blocks. Since this never changes in the client it makes sense to use an Astro component (it's equally reasonable to use a framework component for this kind of thing; Astro is server-only by default for all frameworks!).
|
|
@ -1,8 +1,30 @@
|
|||
## 👩🏽💻 Command Line Interface
|
||||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: CLI Reference
|
||||
---
|
||||
|
||||
### Global Flags
|
||||
## Commands
|
||||
|
||||
#### `--config path`
|
||||
### `astro dev`
|
||||
|
||||
Runs the Astro development server. This starts an HTTP server that responds to requests for pages stored in `src/pages` (or which folder is specified in your [configuration](../README.md##%EF%B8%8F-configuration)).
|
||||
|
||||
See the [dev server](./dev.md) docs for more information on how the dev server works.
|
||||
|
||||
**Flags**
|
||||
|
||||
#### `--port`
|
||||
|
||||
Specifies should port to run on. Defaults to `3000`.
|
||||
|
||||
### `astro build`
|
||||
|
||||
Builds your site for production.
|
||||
|
||||
|
||||
## Global Flags
|
||||
|
||||
### `--config path`
|
||||
|
||||
Specify the path to the config file. Defaults to `astro.config.mjs`. Use this if you use a different name for your configuration file or have your config file in another folder.
|
||||
|
||||
|
@ -10,7 +32,7 @@ Specify the path to the config file. Defaults to `astro.config.mjs`. Use this if
|
|||
astro --config config/astro.config.mjs dev
|
||||
```
|
||||
|
||||
#### `--project-root path`
|
||||
### `--project-root path`
|
||||
|
||||
Specify the path to the project root. If not specified the current working directory is assumed to be the root.
|
||||
|
||||
|
@ -20,32 +42,18 @@ The root is used for finding the Astro configuration file.
|
|||
astro --project-root examples/snowpack dev
|
||||
```
|
||||
|
||||
#### `--reload`
|
||||
### `--reload`
|
||||
|
||||
Clears the cache (dependencies are built within Astro apps).
|
||||
|
||||
#### `--verbose`
|
||||
### `--verbose`
|
||||
|
||||
Enables verbose logging, which is helpful when debugging an issue.
|
||||
|
||||
#### `--version`
|
||||
### `--version`
|
||||
|
||||
Print the Astro version number and exit.
|
||||
|
||||
#### `--help`
|
||||
### `--help`
|
||||
|
||||
Print the help message and exit.
|
||||
|
||||
### Commands
|
||||
|
||||
#### `astro dev`
|
||||
|
||||
Runs the Astro development server. This starts an HTTP server that responds to requests for pages stored in `src/pages` (or which folder is specified in your [configuration](../README.md##%EF%B8%8F-configuration)).
|
||||
|
||||
See the [dev server](./dev.md) docs for more information on how the dev server works.
|
||||
|
||||
**Flags**
|
||||
|
||||
##### `--port`
|
||||
|
||||
Specifies should port to run on. Defaults to `3000`.
|
|
@ -1,4 +1,7 @@
|
|||
# ⚙️ Configuration
|
||||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: Configuration Reference
|
||||
---
|
||||
|
||||
To configure Astro, add an `astro.config.mjs` file in the root of your project. All settings are optional. Here are the defaults:
|
||||
|
||||
|
@ -21,3 +24,7 @@ export default {
|
|||
renderers: ['@astrojs/renderer-svelte', '@astrojs/renderer-vue', '@astrojs/renderer-react', '@astrojs/renderer-preact'],
|
||||
};
|
||||
```
|
||||
|
||||
## Snowpack Config
|
||||
|
||||
Astro is powered internally by Snowpack. You can configure Snowpack directly by creating a `snowpack.config.js` file. See [snowpack.dev](https://www.snowpack.dev/reference/configuration) for full documentation on this file.
|
157
docs/reference/renderer-reference.md
Normal file
157
docs/reference/renderer-reference.md
Normal file
|
@ -0,0 +1,157 @@
|
|||
---
|
||||
layout: ~/layouts/Main.astro
|
||||
title: UI Renderers
|
||||
---
|
||||
|
||||
Astro is designed to support your favorite UI frameworks. [React](https://npm.im/@astrojs/renderer-react), [Svelte](https://npm.im/@astrojs/renderer-svelte), [Vue](https://npm.im/@astrojs/renderer-vue), and [Preact](https://npm.im/@astrojs/renderer-preact) are all built-in to Astro and supported out of the box. No configuration is needed to enable these.
|
||||
|
||||
Internally, each framework is supported via a framework **renderer.** A renderer is a type of Astro plugin that adds support for a framework. Some are built-in, but you can also provide your own third-party renderers to add Astro support for new frameworks.
|
||||
|
||||
## What is a renderer?
|
||||
|
||||
A renderer is an NPM package that has two responsiblities:
|
||||
|
||||
1. _render a component to a static string of HTML_ at build time
|
||||
2. _rehydrate that HTML to create an interactive component_ on the client.
|
||||
|
||||
Take a look at any one of Astro's built-in [`renderers`](https://github.com/snowpackjs/astro/tree/main/packages/renderers) to see this in action. We'll go into more detail in the following sections.
|
||||
|
||||
## Building Your Own Renderer
|
||||
|
||||
> **Building a renderer?** We'd love for you to contribute renderers for popular frameworks back to the Astro repo. Feel free to open an issue or pull request to discuss.
|
||||
|
||||
A simple renderer only needs a few files:
|
||||
|
||||
```
|
||||
/my-custom-renderer/
|
||||
├── package.json
|
||||
├── index.js
|
||||
├── server.js
|
||||
└── client.js
|
||||
```
|
||||
|
||||
### Package Manifest (`package.json`)
|
||||
|
||||
A renderer should include any framework dependencies as package dependencies. For example, `@astrojs/renderer-react` includes `react` & `react-dom` as dependencies in the `package.json` manifest.
|
||||
|
||||
```js
|
||||
// package.json
|
||||
"name": "@astrojs/renderer-react",
|
||||
"dependencies": {
|
||||
"react": "^17.0.0",
|
||||
"react-dom": "^17.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
This means that Astro users don't need to install the UI framework packages themselves. The renderer is the only package that your users will need to install.
|
||||
|
||||
### Renderer Entrypoint (`index.js`)
|
||||
|
||||
The main entrypoint of a renderer is a simple JS file which exports a manifest for the renderer. The required values are `name`, `server`, and `client`.
|
||||
|
||||
Additionally, this entrypoint can define a [Snowpack plugin](https://www.snowpack.dev/guides/plugins) that should be used to load non-JavaScript files.
|
||||
|
||||
```js
|
||||
export default {
|
||||
name: '@astrojs/renderer-xxx', // the renderer name
|
||||
client: './client.js', // relative path to the client entrypoint
|
||||
server: './server.js', // relative path to the server entrypoint
|
||||
snowpackPlugin: '@snowpack/plugin-xxx', // optional, the name of a snowpack plugin to inject
|
||||
snowpackPluginOptions: { example: true }, // optional, any options to be forwarded to the snowpack plugin
|
||||
knownEntrypoint: ['framework'], // optional, entrypoint modules that will be used by compiled source
|
||||
};
|
||||
```
|
||||
|
||||
### Server Entrypoint (`server.js`)
|
||||
|
||||
The server entrypoint of a renderer is responsible for checking if a component should use this renderer, and if so, how that component should be rendered to a string of static HTML.
|
||||
|
||||
```js
|
||||
export default {
|
||||
// should Component use this renderer?
|
||||
check(Component, props, childHTML) {},
|
||||
// Component => string of static HTML
|
||||
renderToStaticMarkup(Component, props, childHTML) {},
|
||||
};
|
||||
```
|
||||
|
||||
#### `check`
|
||||
|
||||
`check` is a function that determines whether a Component should be "claimed" by this renderer.
|
||||
|
||||
In it's simplest form, it can check for the existence of a flag on Object-based components.
|
||||
|
||||
```js
|
||||
function check(Component) {
|
||||
return Component.isMyFrameworkComponent;
|
||||
}
|
||||
```
|
||||
|
||||
In more complex scenarios, like when a Component is a `Function` without any flags, you may need to use `try/catch` to attempt a full render. This result is cached so that it only runs once per-component.
|
||||
|
||||
```js
|
||||
function check(Component, props, childHTML) {
|
||||
try {
|
||||
const { html } = renderToStaticMarkup(Component, props, childHTML);
|
||||
return Boolean(html);
|
||||
} catch (e) {}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
#### `renderToStaticMarkup`
|
||||
|
||||
`renderToStaticMarkup` is a function that renders a Component to a static string of HTML. There's usually a method exported by frameworks named something like `renderToString`.
|
||||
|
||||
```js
|
||||
import { renderToString } from 'xxx';
|
||||
|
||||
function renderToStaticMarkup(Component, props, childHTML) {
|
||||
const html = renderToString(h(Component, { ...props, innerHTML: childHTML }));
|
||||
return { html };
|
||||
}
|
||||
```
|
||||
|
||||
Note that `childHTML` is an HTML string representing this component's children. If your framework does not support rendering HTML directly, you are welcome to use a wrapper component. By convention, Astro uses the `astro-fragment` custom element to inject `childHTML` into. Your renderer should use that, too.
|
||||
|
||||
```js
|
||||
import { h, renderToString } from 'xxx';
|
||||
|
||||
const Wrapper = ({ value }) => h('astro-fragment', { dangerouslySetInnerHTML: { __html: value } });
|
||||
|
||||
function renderToStaticMarkup(Component, props, childHTML) {
|
||||
const html = renderToString(h(Component, props, h(Wrapper, { value: childHTML })));
|
||||
return { html };
|
||||
}
|
||||
```
|
||||
|
||||
### Client Entrypoint (`client.js`)
|
||||
|
||||
The client entrypoint of a renderer is responsible for rehydrating static HTML (the result of `renderToStaticMarkup`) back into a fully interactive component. Its `default` export should be a `function` which accepts the host element of the Component, an `astro-root` custom element.
|
||||
|
||||
> If your framework supports non-destructive component hydration (as opposed to a destructive `render` method), be sure to use that! Following your framework's Server Side Rendering (SSR) guide should point you in the right direction.
|
||||
|
||||
```js
|
||||
import { hydrate } from 'xxx';
|
||||
|
||||
export default (element) => {
|
||||
return (Component, props, childHTML) => {
|
||||
hydrate(h(Component, { ...props, innerHTML: childHTML }), element);
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Note that `childHTML` is an HTML string representing this component's children. If your framework does not support rendering HTML directly, you should use the same wrapper component you used for the server entrypoint.
|
||||
|
||||
```js
|
||||
import { h, hydrate } from 'xxx';
|
||||
import SharedWrapper from './SharedWrapper.js';
|
||||
|
||||
export default (element) => {
|
||||
return (Component, props, childHTML) => {
|
||||
hydrate(h(Component, props, h(SharedWrapper, { value: childHTML })), element);
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
[astro-config]: ./config.md
|
|
@ -225,21 +225,17 @@ Astro is able to render [React](https://npm.im/@astrojs/renderer-react), [Svelte
|
|||
|
||||
👉 [**Command Line Docs**][docs-cli]
|
||||
|
||||
## 🏗 Development Server
|
||||
|
||||
👉 [**Dev Server Docs**][docs-dev]
|
||||
|
||||
[docs-config]: /docs/config.md
|
||||
[docs-config]: /docs/reference/configuration-reference.md
|
||||
[docs-snowpack-config]: https://www.snowpack.dev/reference/configuration
|
||||
[docs-syntax]: /docs/syntax.md
|
||||
[docs-api]: /docs/api.md
|
||||
[docs-renderer]: /docs/renderers.md
|
||||
[docs-collections]: /docs/collections.md
|
||||
[docs-markdown]: /docs/markdown.md
|
||||
[docs-dev]: /docs/dev.md
|
||||
[docs-styling]: /docs/styling.md
|
||||
[docs-syntax]: /docs/core-concepts/astro-components.md
|
||||
[docs-api]: /docs/reference/api-reference.md
|
||||
[docs-renderer]: /docs/core-concepts/ui-renderers.md
|
||||
[docs-collections]: /docs/core-concepts/collections.md
|
||||
[docs-markdown]: /docs/guides/markdown-content.md
|
||||
[docs-styling]: /docs/guides/styling.md
|
||||
[example-blog]: /examples/blog
|
||||
[fetch-content]: /docs/api.md#fetchcontent
|
||||
[fetch-content]: /docs/reference/api-reference.md
|
||||
[fetch-js]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
|
||||
[remark]: https://github.com/remarkjs/remark
|
||||
[mdx]: https://mdxjs.com/
|
||||
|
@ -247,5 +243,5 @@ Astro is able to render [React](https://npm.im/@astrojs/renderer-react), [Svelte
|
|||
[mdn-ric]: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback
|
||||
[partial-hydration]: #-partial-hydration
|
||||
[routing]: #-routing
|
||||
[docs-cli]: /docs/cli.md
|
||||
[docs-publishing]: /docs/publishing.md
|
||||
[docs-cli]: /docs/reference/cli-reference.md
|
||||
[docs-publishing]: /docs/guides/publish-to-npm.md
|
||||
|
|
Loading…
Reference in a new issue