{publishDate}
20 |├── .env.example ├── .gitignore ├── .npmrc ├── .stackblitzrc ├── README.md ├── astro.config.mjs ├── package-lock.json ├── package.json ├── public ├── assets │ └── blog │ │ └── introducing-astro.jpg ├── blog.css ├── favicon.ico ├── global.css ├── search.css ├── search.js ├── social.jpg └── social.png ├── src ├── components │ ├── Author.astro │ ├── BaseHead.astro │ ├── BlogHeader.astro │ ├── BlogPost.astro │ ├── BlogPostPreview.astro │ └── Logo.astro ├── layouts │ └── BlogPost.astro ├── lib │ └── typesense.js └── pages │ ├── index.astro │ ├── posts │ ├── astro-2.md │ ├── astro-3.md │ └── introducing-astro.md │ ├── search.astro │ └── search.json.astro └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | TYPESENSE_HOST=xxx.a1.typesense.net 2 | TYPESENSE_PORT=443 3 | TYPESENSE_PROTOCOL=https 4 | TYPESENSE_ADMIN_KEY=xxx 5 | TYPESENSE_SEARCH_KEY=xxx 6 | SEARCH_ENDPOINT=http://localhost:3000/search.json -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist 3 | 4 | # dependencies 5 | node_modules/ 6 | .snowpack/ 7 | 8 | # logs 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | 13 | # environment variables 14 | .env 15 | .env.production 16 | 17 | # macOS-specific files 18 | .DS_Store 19 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | ## force pnpm to hoist 2 | shamefully-hoist = true -------------------------------------------------------------------------------- /.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "startCommand": "npm start", 3 | "env": { 4 | "ENABLE_CJS_IMPORTS": true 5 | } 6 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Astro Starter Kit: Blog 2 | 3 | ``` 4 | npm init astro -- --template blog 5 | ``` 6 | 7 | [](https://stackblitz.com/github/snowpackjs/astro/tree/latest/examples/blog) 8 | 9 | > 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun! 10 | 11 | Features: 12 | 13 | - ✅ SEO-friendly setup with canonical URLs and OpenGraph data 14 | - ✅ Full Markdown support 15 | - ✅ RSS 2.0 generation 16 | - ✅ Sitemap.xml generation 17 | 18 | ## 🚀 Project Structure 19 | 20 | Inside of your Astro project, you'll see the following folders and files: 21 | 22 | ``` 23 | / 24 | ├── public/ 25 | │ ├── robots.txt 26 | │ └── favicon.ico 27 | ├── src/ 28 | │ ├── components/ 29 | │ │ └── Tour.astro 30 | │ └── pages/ 31 | │ └── index.astro 32 | └── package.json 33 | ``` 34 | 35 | Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. 36 | 37 | There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. 38 | 39 | Any static assets, like images, can be placed in the `public/` directory. 40 | 41 | ## 🧞 Commands 42 | 43 | All commands are run from the root of the project, from a terminal: 44 | 45 | | Command | Action | 46 | | :-------------- | :------------------------------------------ | 47 | | `npm install` | Installs dependencies | 48 | | `npm run dev` | Starts local dev server at `localhost:3000` | 49 | | `npm run build` | Build your production site to `./dist/` | 50 | 51 | ## 👀 Want to learn more? 52 | 53 | Feel free to check [our documentation](https://github.com/snowpackjs/astro) or jump into our [Discord server](https://astro.build/chat). 54 | -------------------------------------------------------------------------------- /astro.config.mjs: -------------------------------------------------------------------------------- 1 | // Full Astro Configuration API Documentation: 2 | // https://docs.astro.build/reference/configuration-reference 3 | 4 | // @type-check enabled! 5 | // VSCode and other TypeScript-enabled text editors will provide auto-completion, 6 | // helpful tooltips, and warnings if your exported object is invalid. 7 | // You can disable this by removing "@ts-check" and `@type` comments below. 8 | 9 | // @ts-check 10 | export default /** @type {import('astro').AstroUserConfig} */ ({ 11 | // Enable the Preact renderer to support Preact JSX components. 12 | renderers: ["@astrojs/renderer-preact", "@astrojs/renderer-vue"], 13 | }); 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/blog", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "prebuild": "node src/lib/typesense.js", 10 | "preview": "astro preview" 11 | }, 12 | "devDependencies": { 13 | "@astrojs/renderer-preact": "^0.2.2", 14 | "astro": "^0.20.7", 15 | "dotenv": "^10.0.0" 16 | }, 17 | "dependencies": { 18 | "typesense": "^0.15.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /public/assets/blog/introducing-astro.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebelchris/astro-typesense-search/7b698068ed4218265fd5469f1dc24ab4093a53d4/public/assets/blog/introducing-astro.jpg -------------------------------------------------------------------------------- /public/blog.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, 3 | sans-serif, Apple Color Emoji, Segoe UI Emoji; 4 | --font-body: "IBM Plex Sans", var(--font-fallback); 5 | --font-mono: "IBM Plex Mono", Consolas, "Andale Mono WT", "Andale Mono", 6 | "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", 7 | "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, 8 | "Courier New", Courier, monospace; 9 | 10 | --color-white: #fff; 11 | --color-black: #000014; 12 | 13 | --color-gray-50: #f9fafb; 14 | --color-gray-100: #f3f4f6; 15 | --color-gray-200: #e5e7eb; 16 | --color-gray-300: #d1d5db; 17 | --color-gray-400: #9ca3af; 18 | --color-gray-500: #6b7280; 19 | --color-gray-600: #4b5563; 20 | --color-gray-700: #374151; 21 | --color-gray-800: #1f2937; 22 | --color-gray-900: #111827; 23 | 24 | --color-blue: #3894ff; 25 | --color-blue-rgb: 56, 148, 255; 26 | --color-green: #17c083; 27 | --color-green-rgb: 23, 192, 131; 28 | --color-orange: #ff5d01; 29 | --color-orange-rgb: 255, 93, 1; 30 | --color-purple: #882de7; 31 | --color-purple-rgb: 136, 45, 231; 32 | --color-red: #ff1639; 33 | --color-red-rgb: 255, 22, 57; 34 | --color-yellow: #ffbe2d; 35 | --color-yellow-rgb: 255, 190, 45; 36 | } 37 | 38 | :root { 39 | color-scheme: light; 40 | --theme-accent: var(--color-orange); 41 | --theme-accent-rgb: var(--color-orange-rgb); 42 | --theme-accent-opacity: 0.1; 43 | --theme-divider: var(--color-gray-100); 44 | --theme-text: var(--color-gray-800); 45 | --theme-text-light: var(--color-gray-600); 46 | --theme-text-lighter: var(--color-gray-400); 47 | --theme-bg: var(--color-white); 48 | --theme-bg-offset: var(--color-gray-100); 49 | --theme-bg-accent: rgba(var(--theme-accent-rgb), var(--theme-accent-opacity)); 50 | --theme-code-inline-bg: var(--color-gray-100); 51 | --theme-code-text: var(--color-gray-100); 52 | --theme-code-bg: var(--color-gray-700); 53 | } 54 | 55 | body { 56 | background: var(--theme-bg); 57 | color: var(--theme-text); 58 | } 59 | 60 | :root.theme-dark { 61 | color-scheme: dark; 62 | --theme-accent-opacity: 0.3; 63 | --theme-divider: var(--color-gray-900); 64 | --theme-text: var(--color-gray-200); 65 | --theme-text-light: var(--color-gray-400); 66 | --theme-text-lighter: var(--color-gray-600); 67 | --theme-bg: var(--color-black); 68 | --theme-bg-offset: var(--color-gray-900); 69 | --theme-code-inline-bg: var(--color-gray-800); 70 | --theme-code-text: var(--color-gray-200); 71 | --theme-code-bg: var(--color-gray-900); 72 | } 73 | 74 | ::selection { 75 | color: var(--theme-accent); 76 | background-color: rgba(var(--theme-accent-rgb), var(--theme-accent-opacity)); 77 | } 78 | 79 | * { 80 | box-sizing: border-box; 81 | margin: 0; 82 | } 83 | 84 | :root { 85 | --user-font-scale: 1rem - 16px; 86 | --max-width: calc(100% - 2rem); 87 | } 88 | 89 | @media (min-width: 50em) { 90 | :root { 91 | --max-width: 40em; 92 | } 93 | } 94 | 95 | body { 96 | display: flex; 97 | flex-direction: column; 98 | min-height: 100vh; 99 | font-family: var(--font-body); 100 | font-size: 1rem; 101 | font-size: clamp( 102 | 0.875rem, 103 | 0.4626rem + 1.0309vw + var(--user-font-scale), 104 | 1.125rem 105 | ); 106 | line-height: 1.625; 107 | } 108 | 109 | body { 110 | width: 100%; 111 | display: grid; 112 | --gutter: 0.5rem; 113 | --doc-padding: 2rem; 114 | } 115 | 116 | .layout { 117 | display: grid; 118 | grid-auto-flow: column; 119 | grid-template-columns: minmax(var(--gutter), 1fr) minmax(0, var(--max-width)) minmax( 120 | var(--gutter), 121 | 1fr 122 | ); 123 | gap: 1em; 124 | } 125 | 126 | .layout > article { 127 | grid-column: 2; 128 | } 129 | 130 | nav ul { 131 | list-style: none; 132 | padding: 0; 133 | } 134 | 135 | /* Typography */ 136 | :is(h1, h2, h3, h4, h5, h6) { 137 | margin-bottom: 1.38rem; 138 | font-weight: 400; 139 | line-height: 1.3; 140 | } 141 | 142 | :is(h1, h2) { 143 | max-width: 40ch; 144 | } 145 | 146 | :is(h2, h3):not(:first-child) { 147 | margin-top: 3rem; 148 | } 149 | 150 | h1 { 151 | font-size: clamp(2.488rem, 1.924rem + 1.41vw, 3.052rem); 152 | } 153 | 154 | h2 { 155 | font-size: clamp(2.074rem, 1.707rem + 0.9175vw, 2.441rem); 156 | } 157 | 158 | h3 { 159 | font-size: clamp(1.728rem, 1.503rem + 0.5625vw, 1.953rem); 160 | } 161 | 162 | h4 { 163 | font-size: clamp(1.44rem, 1.317rem + 0.3075vw, 1.563rem); 164 | } 165 | 166 | h5 { 167 | font-size: clamp(1.2rem, 1.15rem + 0.125vw, 1.25rem); 168 | } 169 | 170 | p { 171 | color: var(--theme-text-light); 172 | } 173 | 174 | small, 175 | .text_small { 176 | font-size: 0.833rem; 177 | } 178 | 179 | a { 180 | color: var(--theme-accent); 181 | font-weight: 400; 182 | text-underline-offset: 0.08em; 183 | text-decoration: none; 184 | align-items: center; 185 | gap: 0.5rem; 186 | } 187 | 188 | a > code:not([class*="language"]) { 189 | position: relative; 190 | color: var(--theme-accent); 191 | background: transparent; 192 | text-underline-offset: var(--padding-block); 193 | } 194 | 195 | a > code:not([class*="language"])::before { 196 | content: ""; 197 | position: absolute; 198 | top: 0; 199 | right: 0; 200 | bottom: 0; 201 | left: 0; 202 | display: block; 203 | background: var(--theme-accent); 204 | opacity: var(--theme-accent-opacity); 205 | border-radius: var(--border-radius); 206 | } 207 | 208 | a:hover, 209 | a:focus { 210 | text-decoration: underline; 211 | } 212 | 213 | a:focus { 214 | outline: 2px solid currentColor; 215 | outline-offset: 0.25em; 216 | } 217 | 218 | strong { 219 | font-weight: 600; 220 | color: inherit; 221 | } 222 | 223 | /* Supporting Content */ 224 | 225 | code:not([class*="language"]) { 226 | --border-radius: 3px; 227 | --padding-block: 0.2rem; 228 | --padding-inline: 0.33rem; 229 | 230 | font-family: var(--font-mono); 231 | font-size: 0.85em; 232 | color: inherit; 233 | background-color: var(--theme-code-inline-bg); 234 | padding: var(--padding-block) var(--padding-inline); 235 | margin: calc(var(--padding-block) * -1) -0.125em; 236 | border-radius: var(--border-radius); 237 | } 238 | 239 | pre > code:not([class*="language"]) { 240 | background-color: transparent; 241 | padding: 0; 242 | margin: 0; 243 | border-radius: 0; 244 | color: inherit; 245 | } 246 | 247 | pre { 248 | position: relative; 249 | background-color: var(--theme-code-bg); 250 | color: var(--theme-code-text); 251 | --padding-block: 1rem; 252 | --padding-inline: 2rem; 253 | padding: var(--padding-block) var(--padding-inline); 254 | padding-right: calc(var(--padding-inline) * 2); 255 | margin-left: calc(50vw - var(--padding-inline)); 256 | transform: translateX(-50vw); 257 | 258 | line-height: 1.414; 259 | width: calc(100vw + (var(--padding-inline) * 2)); 260 | max-width: calc(100% + (var(--padding-inline) * 2)); 261 | overflow-y: hidden; 262 | overflow-x: auto; 263 | } 264 | 265 | @media (min-width: 37.75em) { 266 | pre { 267 | --padding-inline: 1.25rem; 268 | border-radius: 8px; 269 | } 270 | } 271 | 272 | .flex { 273 | display: flex; 274 | align-items: center; 275 | } 276 | 277 | img.cover { 278 | width: 100%; 279 | max-height: 50vh; 280 | object-fit: cover; 281 | } 282 | 283 | blockquote { 284 | font-size: 1.5rem; 285 | --padding-block: 1rem; 286 | --padding-inline: 1.25rem; 287 | --color: var(--theme-divider); 288 | 289 | display: flex; 290 | flex-direction: column; 291 | 292 | padding: var(--padding-block) var(--padding-inline); 293 | margin-left: calc(var(--padding-inline) * -1); 294 | margin-right: calc(var(--padding-inline) * -1); 295 | 296 | background: transparent; 297 | border-left: calc(var(--padding-inline) / 2) solid var(--color); 298 | border-radius: 0; 299 | } 300 | 301 | blockquote .source { 302 | font-weight: 500; 303 | color: var(--color); 304 | font-size: 1rem; 305 | } 306 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebelchris/astro-typesense-search/7b698068ed4218265fd5469f1dc24ab4093a53d4/public/favicon.ico -------------------------------------------------------------------------------- /public/global.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --font-sans: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", 3 | Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; 4 | --font-mono: "IBM Plex Mono", Consolas, "Andale Mono WT", "Andale Mono", 5 | "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", 6 | "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, 7 | "Courier New", Courier, monospace; 8 | --color-green: #17c083; 9 | } 10 | 11 | * { 12 | box-sizing: border-box; 13 | margin: 0; 14 | } 15 | 16 | html { 17 | display: grid; 18 | width: 100%; 19 | max-width: 100vw; 20 | overflow: hidden; 21 | height: 100%; 22 | background-color: #000014; 23 | } 24 | 25 | html, 26 | body { 27 | padding: 0; 28 | font-size: clamp(14px, calc(1rem + (3vw - 1.2rem)), 20px); 29 | font-family: var(--font-sans); 30 | font-weight: 400; 31 | background-image: radial-gradient( 32 | 87.7% 87.7% at 85.6% 18.14%, 33 | #111827 0%, 34 | #000014 100% 35 | ); 36 | background-repeat: no-repeat; 37 | color: #f3f4f6; 38 | } 39 | 40 | body { 41 | position: relative; 42 | display: grid; 43 | place-items: center; 44 | min-width: 100%; 45 | max-width: 100vw; 46 | min-height: 100vh; 47 | overflow-x: hidden; 48 | } 49 | 50 | .visually-hidden { 51 | clip: rect(0 0 0 0); 52 | clip-path: inset(50%); 53 | height: 1px; 54 | overflow: hidden; 55 | position: absolute; 56 | white-space: nowrap; 57 | width: 1px; 58 | } 59 | 60 | a { 61 | position: relative; 62 | text-decoration: none; 63 | color: var(--color-green); 64 | padding: 0.05em 0.125em; 65 | margin: -0.05em -0.125em; 66 | transition: color 120ms cubic-bezier(0.23, 1, 0.32, 1); 67 | z-index: 0; 68 | display: inline-block; 69 | } 70 | 71 | a:hover, 72 | a:focus { 73 | color: black; 74 | } 75 | 76 | a:hover::before, 77 | a:focus::before { 78 | transform: scaleY(1); 79 | background: var(--color-green); 80 | } 81 | 82 | a:visited { 83 | color: var(--color-green); 84 | } 85 | 86 | a:visited:hover, 87 | a:visited:focus { 88 | color: black; 89 | } 90 | 91 | a::before { 92 | transform-origin: bottom center; 93 | content: ""; 94 | display: block; 95 | position: absolute; 96 | top: 0; 97 | right: 0; 98 | bottom: 0; 99 | left: 0; 100 | inset: 0; 101 | background: var(--color-green); 102 | pointer-events: none; 103 | transform: scaleY(0.05); 104 | transition: transform 120ms cubic-bezier(0.23, 1, 0.32, 1), 105 | background 120ms cubic-bezier(0.23, 1, 0.32, 1); 106 | z-index: -1; 107 | } 108 | -------------------------------------------------------------------------------- /public/search.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, 3 | sans-serif, Apple Color Emoji, Segoe UI Emoji; 4 | --font-body: "IBM Plex Sans", var(--font-fallback); 5 | --font-mono: "IBM Plex Mono", Consolas, "Andale Mono WT", "Andale Mono", 6 | "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", 7 | "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, 8 | "Courier New", Courier, monospace; 9 | 10 | --color-white: #fff; 11 | --color-black: #000014; 12 | 13 | --color-gray-50: #f9fafb; 14 | --color-gray-100: #f3f4f6; 15 | --color-gray-200: #e5e7eb; 16 | --color-gray-300: #d1d5db; 17 | --color-gray-400: #9ca3af; 18 | --color-gray-500: #6b7280; 19 | --color-gray-600: #4b5563; 20 | --color-gray-700: #374151; 21 | --color-gray-800: #1f2937; 22 | --color-gray-900: #111827; 23 | 24 | --color-blue: #3894ff; 25 | --color-blue-rgb: 56, 148, 255; 26 | --color-green: #17c083; 27 | --color-green-rgb: 23, 192, 131; 28 | --color-orange: #ff5d01; 29 | --color-orange-rgb: 255, 93, 1; 30 | --color-purple: #882de7; 31 | --color-purple-rgb: 136, 45, 231; 32 | --color-red: #ff1639; 33 | --color-red-rgb: 255, 22, 57; 34 | --color-yellow: #ffbe2d; 35 | --color-yellow-rgb: 255, 190, 45; 36 | } 37 | 38 | :root { 39 | color-scheme: light; 40 | --theme-accent: var(--color-orange); 41 | --theme-accent-rgb: var(--color-orange-rgb); 42 | --theme-accent-opacity: 0.1; 43 | --theme-divider: var(--color-gray-100); 44 | --theme-text: var(--color-gray-800); 45 | --theme-text-light: var(--color-gray-600); 46 | --theme-text-lighter: var(--color-gray-400); 47 | --theme-bg: var(--color-white); 48 | --theme-bg-offset: var(--color-gray-100); 49 | --theme-bg-accent: rgba(var(--theme-accent-rgb), var(--theme-accent-opacity)); 50 | --theme-code-inline-bg: var(--color-gray-100); 51 | --theme-code-text: var(--color-gray-100); 52 | --theme-code-bg: var(--color-gray-700); 53 | } 54 | 55 | body { 56 | background: var(--theme-bg); 57 | color: var(--theme-text); 58 | } 59 | 60 | :root.theme-dark { 61 | color-scheme: dark; 62 | --theme-accent-opacity: 0.3; 63 | --theme-divider: var(--color-gray-900); 64 | --theme-text: var(--color-gray-200); 65 | --theme-text-light: var(--color-gray-400); 66 | --theme-text-lighter: var(--color-gray-600); 67 | --theme-bg: var(--color-black); 68 | --theme-bg-offset: var(--color-gray-900); 69 | --theme-code-inline-bg: var(--color-gray-800); 70 | --theme-code-text: var(--color-gray-200); 71 | --theme-code-bg: var(--color-gray-900); 72 | } 73 | 74 | ::selection { 75 | color: var(--theme-accent); 76 | background-color: rgba(var(--theme-accent-rgb), var(--theme-accent-opacity)); 77 | } 78 | 79 | * { 80 | box-sizing: border-box; 81 | margin: 0; 82 | } 83 | 84 | :root { 85 | --user-font-scale: 1rem - 16px; 86 | --max-width: calc(100% - 2rem); 87 | } 88 | 89 | @media (min-width: 50em) { 90 | :root { 91 | --max-width: 40em; 92 | } 93 | } 94 | 95 | body { 96 | display: flex; 97 | flex-direction: column; 98 | font-family: var(--font-body); 99 | font-size: 1rem; 100 | font-size: clamp( 101 | 0.875rem, 102 | 0.4626rem + 1.0309vw + var(--user-font-scale), 103 | 1.125rem 104 | ); 105 | line-height: 1.625; 106 | } 107 | 108 | body { 109 | width: 100%; 110 | display: grid; 111 | --gutter: 0.5rem; 112 | --doc-padding: 2rem; 113 | } 114 | 115 | .layout { 116 | display: grid; 117 | grid-auto-flow: column; 118 | grid-template-columns: minmax(var(--gutter), 1fr) minmax(0, var(--max-width)) minmax( 119 | var(--gutter), 120 | 1fr 121 | ); 122 | gap: 1em; 123 | } 124 | 125 | .layout > article { 126 | grid-column: 2; 127 | } 128 | 129 | nav ul { 130 | list-style: none; 131 | padding: 0; 132 | } 133 | 134 | /* Typography */ 135 | :is(h1, h2, h3, h4, h5, h6) { 136 | margin-bottom: 1.38rem; 137 | font-weight: 400; 138 | line-height: 1.3; 139 | } 140 | 141 | :is(h1, h2) { 142 | max-width: 40ch; 143 | } 144 | 145 | :is(h2, h3):not(:first-child) { 146 | margin-top: 3rem; 147 | } 148 | 149 | h1 { 150 | font-size: clamp(2.488rem, 1.924rem + 1.41vw, 3.052rem); 151 | } 152 | 153 | h2 { 154 | font-size: clamp(2.074rem, 1.707rem + 0.9175vw, 2.441rem); 155 | } 156 | 157 | h3 { 158 | font-size: clamp(1.728rem, 1.503rem + 0.5625vw, 1.953rem); 159 | } 160 | 161 | h4 { 162 | font-size: clamp(1.44rem, 1.317rem + 0.3075vw, 1.563rem); 163 | } 164 | 165 | h5 { 166 | font-size: clamp(1.2rem, 1.15rem + 0.125vw, 1.25rem); 167 | } 168 | 169 | p { 170 | color: var(--theme-text-light); 171 | } 172 | 173 | small, 174 | .text_small { 175 | font-size: 0.833rem; 176 | } 177 | 178 | a { 179 | color: var(--theme-accent); 180 | font-weight: 400; 181 | text-underline-offset: 0.08em; 182 | text-decoration: none; 183 | align-items: center; 184 | gap: 0.5rem; 185 | } 186 | 187 | a > code:not([class*="language"]) { 188 | position: relative; 189 | color: var(--theme-accent); 190 | background: transparent; 191 | text-underline-offset: var(--padding-block); 192 | } 193 | 194 | a > code:not([class*="language"])::before { 195 | content: ""; 196 | position: absolute; 197 | top: 0; 198 | right: 0; 199 | bottom: 0; 200 | left: 0; 201 | display: block; 202 | background: var(--theme-accent); 203 | opacity: var(--theme-accent-opacity); 204 | border-radius: var(--border-radius); 205 | } 206 | 207 | a:hover, 208 | a:focus { 209 | text-decoration: underline; 210 | } 211 | 212 | a:focus { 213 | outline: 2px solid currentColor; 214 | outline-offset: 0.25em; 215 | } 216 | 217 | strong { 218 | font-weight: 600; 219 | color: inherit; 220 | } 221 | 222 | /* Supporting Content */ 223 | 224 | code:not([class*="language"]) { 225 | --border-radius: 3px; 226 | --padding-block: 0.2rem; 227 | --padding-inline: 0.33rem; 228 | 229 | font-family: var(--font-mono); 230 | font-size: 0.85em; 231 | color: inherit; 232 | background-color: var(--theme-code-inline-bg); 233 | padding: var(--padding-block) var(--padding-inline); 234 | margin: calc(var(--padding-block) * -1) -0.125em; 235 | border-radius: var(--border-radius); 236 | } 237 | 238 | pre > code:not([class*="language"]) { 239 | background-color: transparent; 240 | padding: 0; 241 | margin: 0; 242 | border-radius: 0; 243 | color: inherit; 244 | } 245 | 246 | pre { 247 | position: relative; 248 | background-color: var(--theme-code-bg); 249 | color: var(--theme-code-text); 250 | --padding-block: 1rem; 251 | --padding-inline: 2rem; 252 | padding: var(--padding-block) var(--padding-inline); 253 | padding-right: calc(var(--padding-inline) * 2); 254 | margin-left: calc(50vw - var(--padding-inline)); 255 | transform: translateX(-50vw); 256 | 257 | line-height: 1.414; 258 | width: calc(100vw + (var(--padding-inline) * 2)); 259 | max-width: calc(100% + (var(--padding-inline) * 2)); 260 | overflow-y: hidden; 261 | overflow-x: auto; 262 | } 263 | 264 | @media (min-width: 37.75em) { 265 | pre { 266 | --padding-inline: 1.25rem; 267 | border-radius: 8px; 268 | } 269 | } 270 | 271 | .flex { 272 | display: flex; 273 | align-items: center; 274 | } 275 | 276 | img.cover { 277 | width: 100%; 278 | max-height: 50vh; 279 | object-fit: cover; 280 | } 281 | 282 | blockquote { 283 | font-size: 1.5rem; 284 | --padding-block: 1rem; 285 | --padding-inline: 1.25rem; 286 | --color: var(--theme-divider); 287 | 288 | display: flex; 289 | flex-direction: column; 290 | 291 | padding: var(--padding-block) var(--padding-inline); 292 | margin-left: calc(var(--padding-inline) * -1); 293 | margin-right: calc(var(--padding-inline) * -1); 294 | 295 | background: transparent; 296 | border-left: calc(var(--padding-inline) / 2) solid var(--color); 297 | border-radius: 0; 298 | } 299 | 300 | blockquote .source { 301 | font-weight: 500; 302 | color: var(--color); 303 | font-size: 1rem; 304 | } 305 | ol li { 306 | margin: 2rem 0; 307 | padding-left: 1rem; 308 | } 309 | ol li p { 310 | margin-bottom: 1rem; 311 | } 312 | .ais-SearchBox-form { 313 | display: block; 314 | position: relative; 315 | margin-top: 2rem; 316 | } 317 | .ais-SearchBox-input { 318 | -webkit-appearance: none; 319 | -moz-appearance: none; 320 | appearance: none; 321 | padding: 0.3rem 1.7rem; 322 | width: 100%; 323 | position: relative; 324 | background-color: #fff; 325 | border: 1px solid #c4c8d8; 326 | border-radius: 5px; 327 | } 328 | .ais-SearchBox-loadingIndicator, 329 | .ais-SearchBox-reset, 330 | .ais-SearchBox-submit { 331 | -webkit-appearance: none; 332 | -moz-appearance: none; 333 | appearance: none; 334 | position: absolute; 335 | z-index: 1; 336 | width: 20px; 337 | height: 20px; 338 | top: 50%; 339 | right: 0.3rem; 340 | -webkit-transform: translateY(-50%); 341 | transform: translateY(-50%); 342 | } 343 | .ais-SearchBox-submit { 344 | left: 0.3rem; 345 | } 346 | .ais-SearchBox-reset { 347 | right: 0.3rem; 348 | } 349 | 350 | .ais-ClearRefinements-button, 351 | .ais-CurrentRefinements-delete, 352 | .ais-CurrentRefinements-reset, 353 | .ais-GeoSearch-redo, 354 | .ais-GeoSearch-reset, 355 | .ais-HierarchicalMenu-showMore, 356 | .ais-InfiniteHits-loadMore, 357 | .ais-InfiniteHits-loadPrevious, 358 | .ais-InfiniteResults-loadMore, 359 | .ais-Menu-showMore, 360 | .ais-RangeInput-submit, 361 | .ais-RefinementList-showMore, 362 | .ais-SearchBox-reset, 363 | .ais-SearchBox-submit, 364 | .ais-VoiceSearch-button { 365 | padding: 0; 366 | overflow: visible; 367 | font: inherit; 368 | line-height: normal; 369 | color: inherit; 370 | background: none; 371 | border: 0; 372 | cursor: pointer; 373 | -webkit-user-select: none; 374 | -moz-user-select: none; 375 | -ms-user-select: none; 376 | user-select: none; 377 | } 378 | -------------------------------------------------------------------------------- /public/search.js: -------------------------------------------------------------------------------- 1 | const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({ 2 | server: { 3 | apiKey: TYPESENSE_SEARCH_KEY, 4 | nodes: [ 5 | { 6 | host: TYPESENSE_HOST, 7 | port: TYPESENSE_PORT, 8 | protocol: TYPESENSE_PROTOCOL, 9 | }, 10 | ], 11 | cacheSearchResultsForSeconds: 2 * 60, 12 | }, 13 | additionalSearchParameters: { 14 | queryBy: 'title,description', 15 | }, 16 | }); 17 | const searchClient = typesenseInstantsearchAdapter.searchClient; 18 | const search = instantsearch({ 19 | searchClient, 20 | indexName: 'posts', 21 | }); 22 | search.addWidgets([ 23 | instantsearch.widgets.searchBox({ 24 | container: '#searchbox', 25 | }), 26 | instantsearch.widgets.hits({ 27 | container: '#hits', 28 | templates: { 29 | item: ` 30 |
`, 35 | }, 36 | }), 37 | ]); 38 | search.start(); 39 | -------------------------------------------------------------------------------- /public/social.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebelchris/astro-typesense-search/7b698068ed4218265fd5469f1dc24ab4093a53d4/public/social.jpg -------------------------------------------------------------------------------- /public/social.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebelchris/astro-typesense-search/7b698068ed4218265fd5469f1dc24ab4093a53d4/public/social.png -------------------------------------------------------------------------------- /src/components/Author.astro: -------------------------------------------------------------------------------- 1 | --- 2 | export interface Props { 3 | name: string; 4 | href: string; 5 | } 6 | 7 | const { name, href } = Astro.props; 8 | --- 9 | 10 | 13 | 14 | 19 | -------------------------------------------------------------------------------- /src/components/BaseHead.astro: -------------------------------------------------------------------------------- 1 | --- 2 | export interface Props { 3 | title: string; 4 | description: string; 5 | permalink: string; 6 | } 7 | const { title, description, permalink } = Astro.props; 8 | --- 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |{publishDate}
20 |{post.description}
16 | Read more 17 |{description}
55 |– Jeff Atwood
[Falling Into The Pit of Success](https://blog.codinghorror.com/falling-into-the-pit-of-success/)– Jeff Atwood
[Falling Into The Pit of Success](https://blog.codinghorror.com/falling-into-the-pit-of-success/)– Jeff Atwood
[Falling Into The Pit of Success](https://blog.codinghorror.com/falling-into-the-pit-of-success/){description}
24 |