showcase examples for isolated simple usage patterns
01_basics
This is a minimal example that shows the node version running
- Layout Slots
02_ssr-counter
- integration : @astrojs/node
- adapter : node-standalone
shared global var demo. reload the page to increment the counter. All pages share the same counter
03_sse-counter
- integration : @astrojs/node
- adapter : node-standalone
- Server Endpoints
- ReadableStream
SSE: Server Sent Events. global var using a timer and Emitter
Server keeps couter state. reloading the page has no effect on the counter
requires Node18 Node18 for ReadableStream(), currently only on Gitpod
04_client-counters
A simple approach for multiple instances of a component. A <script> is included once. It initiates all components of a class on page load without requiring unique identification
05_client-uid-counters
Decentralized scoping js execution on an Astro component used mutiple times on the same page
- integration : @astrojs/node
- adapter : node-standalone
Constraints :
- decentralized : not conflicting with multiple integrations using the same concept
- no global state management : which is not easy to fulfill when using components from different sources
- multi instances used on the same page
- components handle their own js scripts
- each component has a lifecylce independence and its js only handles its own html and not one of other instances
Alternatives:
- It is always possible to initialize all components from the top page js, but sometimes the js component code is preferrably placed within the component itself.
- It is also possible within the component to have the code run on all components in the page of the same type, but this does not fit with lazy loading where each component has to be initialize separately
- It is still possible to keep a component state in the window or as html attribute and still run init on all components everytime a new one wakes up, but this might incur incompatibilities when mixing versions
- A centralized approach is also demonstrated but not recommend due to flaws that might happen when the
sequence_uidfunction gets multiple instances for some reason such as being budled separately.
Optionally:
- a hash function could be used if an unidentifieable id is desired that does not reflect the user input (using counting numbers or names,...), if the input data is too big such as complete file or if the uid is required to always have the same consistent format e.g. number of characters which the user cannot guarantee.
06_astro-xelement
Using unified config for all of astro.config.mjs, .astro and .js server files
- integration : @astrojs/node
- adapter : node-standalone
- astro-xelement
07_env-config
using environment variables from file in astro.config.mjs and .js server files
-
integration : @astrojs/node
-
adapter : node-standalone
-
todo test with loadEnv from 'vite'
08_404-error-handling
Page not found redirect to 404
- integration : @astrojs/node
- output server
- adapter : node-standalone
- output static
- dotenv
- Custom 404 Error page
- Dynamic Route with Rest parameters
[...path].astro
custom 404 page from : https://codepen.io/Stephane/pen/Jdozrp
09_dynamic-imports
- integration : @astrojs/node
- adapter : node-standalone
- Deferr loading of js on event or timeout
setTimeout- Dynamic import()
- Spinner while waiting : Astro Component with animated SVG
This is about dynamically importing a js script only when the component logic decides to do it. In this case, after 2 seconds from window load.
Not only <Card title="Test" client:visible/> is not supported by astro as directive reserved for framework components only, but also, it does not give fine granularity to decide exactly when to load a js script.
Note: Testing this example only makes sense in production mode (with build and run). Only gitpod left because it has a shell script that builds and runs by default while the others (StackBliz and Codesandbox) run in preview mode.
10_prerender
This example uses the experimental prerender feature. index page '/' is prerendered while '/rerender' page is server side rendered on every fetch
- integration : @astrojs/node
- adapter : node-standalone
- Hybrid Rendering with
export const prerender=true
11_deno-env
- integration : deno
- adapter : deno
Testing environment variables in deno and deno.deploy
live demo : https://astro-env.deno.dev/
project : https://dash.deno.com/projects/astro-env
12_content-collections
- integration : @astrojs/node
- adapter : node-standalone
- Content Collections
- get all frontmatter meta data with getCollection()
- rendering of multiple Markdown pages in one page with
await Promise.all()and item.render() - Single pages rendering in a dynamic path
[...slug].astrowith getEntryBySlug()
13_client-cookie-counter
- integration : @astrojs/node
- adapter : node-standalone
- Astro API Astro.cookies.get()
This counter uses a cookie counter=1 to persist through pages relaod despite being a client counter.
For Astro SSR there is a simplicity advantage for using a cookie over using client sotrage :
- Automatically sent with every client request
- No display flicker
- no need to create a server endpoint to submit the client updated value (to avoid the flicker)
Note : Only a single counter is used in this example given that a single cookie is used
Note : For a demo using cookies, the Astro.cookies could only be read in Gitpod
references
-
todo : check example with blocking head script can solve ssg
14_client-storage-counter
- This counter is using
sessionStoragefor client side persistency, and therefore avoids cookies. - For UI sensitive elements (such as menu, sidebar, modal,...) it is important to prevent flicker. Such Flicker can happen when the server sends a default value upon page refresh and then javascript adjusts the value after reading it from the session sotrage. To prevent that, every time the client changes the value, the server state needs to be updated through a
putrequest to a server endpoint - For the server to know which client has whic counter, a counters map for each session_id is stored
- The session ID is created by the server when a request URL does not contain
session_idparameter, it is passed to the client within the html components, the client takes it upon page load and use it in case no sessionStorage session_id available. Then stick it to the URL parameters for future queries
Note : this implementation is for demo purpose only and suffers from memory leak as old session_id's are not deleted.
references
15_server-cookie-counter
- adapter : node-standalone
Counts the pages load for a specific client with cookies. This examples shows how to get and set a cookie from a .astro page while example 13 gets the cookie from the server and set it from the client.
16_html-string
example to show how to generate an html string out of a component using a Wrapper and Astro.slots.render()
references
17_dynamic-javascript
Generate javascript that can be executed on the client. The UID set by the server, is fetched by the client inside a javascript file
Note : although functional, this method is not recommended due to Vite complaning about dynamic import and security risk it implies.
18_simple-integration
example using astrojs/image integration
19_images-integration
- adapter : node-standalone
- integration : image
example using astrojs/image integration
20_ssr-cache-proxy
-
adapter : node-standalone
-
proxy : express
-
cache event-drive content
-
call purge method
-
put pass througn
Running mode :
- astro starts with
pnpm run previewlistens on port 4000 - express starts with
pnpm run proxylistens on port 3000 - first client page load from proxy : cache miss, proxy fetches data from SSR
- SSR generates the page and and on creation assigns a page hash
- for the example purpose a 2 seconds timeout is added to a page render
- the page hash is updated on the proxy (in the example through a shared
hashes.jsonbut could be with a db or API) - when the proxy fetches the page it identifies the cached page with its hash (as it is always actual on the
hashes.json) - follow up request checks if page is available and if hash is fresh
- when the user updates the data, the server updates the page hash
- follow up requests on the proxy show the page to be stale due to old cached page, the proxy fetches the page with the new hash
21_ssr-cache-middleware
Same concept as the previous example but here the cache proxy and Astro SSR are combined in the same express App with Astro running in middleware mode
- once a request is fetched from the SSR server, the response contains an ETag with the hash to ensure immediate page update with the just produced hash value
22_mdx-svg
Example for testing SVG usage within .astro, .md and .mdx
This highlights incompatibility of inlined SVG when injected from remark/rehype plugins in an mdx file
- attributes with ':' e.g.
xmlns:xlinkgets treated as .jsx and converted toxmlnsXlink,xmlnsorxmlnsxlink, all of which break the SVG rendering
Note :
- html comments not supported
- html empty new lines of spaces also break the html parsing as indentation takes precendence
references
- github issue withastro/astro#5796 (comment)
- Stackoverflow https://stackoverflow.com/questions/73306060/title-is-undefined-while-generating-sitemap-in-astro
- Stackoverflow https://stackoverflow.com/questions/75119497/how-can-i-filter-frontmatter-in-a-remark-plugin
23_remote-markdown
- adapter : node-standalone
features
astro-remoteworks with astr v2 but not an official integration- Passing default components only
Heading, CodeBlock, CodeSpan, Noteno mapping of custom components, e.g. images,...
references
- Astro docs : https://docs.astro.build/en/guides/markdown-content/#fetching-remote-markdown
- https://github.com/natemoo-re/astro-remote
- demo : https://github.com/natemoo-re/astro-remote/tree/main/packages/demo
24_api-proxy
4 Locations where to alter server config
/vite.config.js/astro.config.mjs:server.port,proxy/astro.config.mjs:site.server.port,proxy/src/libs/inetgration-test.js:config_setup().update_config()
summary
- can Astro proxy a service with the Vite server.proxy feature ?
- No, Astro does not forward server.proxy to Vite
- does Astro need a proxy to access a different port running on the same host ?
- No, because Astro frontmatter runs on the server so has access to localhost ports
references
- Vite feature : https://vitejs.dev/config/server-options.html#server-proxy
- Stack issue : https://stackoverflow.com/questions/73212935/astro-how-to-proxy-service-calls
25_markdown-scale
Benchmark results charts : https://microwebstacks.github.io/astro-examples/
- scalability stress test and limiting facrors (e.g. 15000 pages)
- markdown pages generator
- pages markdown
- pages mdx
- local markdown in .astro
- local mdx in .astro
- remote markdown
References
- Discord 4k pages, static, json ~10kB/page https://discord.com/channels/830184174198718474/1066464117327659111
- nodejs limit 1.7GB https://stackoverflow.com/questions/38558989/node-js-heap-out-of-memory
26_serverless-counter-netlify
./26_serverless-counter-netlify
- integration : @astrojs/netlify
- adapter : netlify
shared global var demo. reload the page to increment the counter. All pages share the same counter
Note ! in serverless deployment, the in-memory state only persistes temporarily until a different instance is started
- live demo on netlify : https://astro-serverless-counter.netlify.app/
27_serverless-counter-cloudflare
./27_serverless-counter-cloudflare
- integration : cloudflare
- adapter : cloudflare
- NODE_VERSION : 16.19.1
- cannot rename deployment url after creation
shared global var demo. reload the page to increment the counter. All pages share the same counter
Note ! in serverless deployment, the in-memory state only persistes temporarily until a different instance is started
- live demo on cloudflare : https://astro-serverless-counter.pages.dev/
28_serverless-counter-vercel
./28_serverless-counter-vercel
- integration : vercel
- adapter : vercel
- free account does not deploy from github organization
shared global var demo. reload the page to increment the counter. All pages share the same counter
Note ! in serverless deployment, the in-memory state only persistes temporarily until a different instance is started
- live demo in vercel : https://astro-serverless-counter.vercel.app/
29_serverless-counter-denodeploy
./29_serverless-counter-denodeploy
- integration : deno
- adapter : deno
- deployment from command line
shared global var demo. reload the page to increment the counter. All pages share the same counter
Note ! in serverless deployment, the in-memory state only persistes temporarily until a different instance is started
.env not taken has to manually inject env var DENO_DEPLOY_TOKEN
- live demo in deno deploy : https://astro-serverless-counter.deno.dev/
30_serverless-counter-deno-redis
./30_serverless-counter-deno-redis
- integration : deno
- adapter : deno
- database : redis
Deno.versionnot working resulting in crash on deploy
demo for variable persisted on redis database. reload the page to increment the counter. All pages share the same counter.
expected environment variables
-
local
DENO_DEPLOY_TOKEN: to be manually injected in the env before callingdeploy -
your redis credentials, needed both locally to be injected manually and on deploy entered on the project settings
- REDIS_URL=******.redislabs.com
- REDIS_PORT=*****
- REDIS_PASSWORD=***********
-
live demo in deno deploy : https://astro-redis-counter.deno.dev/
31_collections-markdoc
- integration : @astrojs/markdoc
- Content Collections mandatory for markdoc
Status
- render : OK
- custom components - nodes : OK
- custom components - tags : wip
32_cms-storyblok
- integration : @storyblok/astro
- env variable in
.envfileSTORYBLOK_TOKENloaded with vite loadEnv in config.js - test with
story.httpusing VSCode REST Client and dotenv from.env
Status
- render : WIP
Upcoming
- deployments : https://docs.astro.build/en/guides/deploy/
- AWS
- Google cloud
- cms : https://docs.astro.build/en/guides/cms/
- Storyblock
- Contentful
- ButterCMS
- Prismic
- Sanity
- jwt (secure cookie)
- request specific context passing in Astro to avoid props drilling
More Astro examples
astro-big doc
- Astro Theme submission https://astro.build/themes/details/astro-big-doc/
- Github repo : https://github.com/MicroWebStacks/astro-big-doc
- Live demo : https://microwebstacks.github.io/astro-big-doc/blog/gallery.mdx/
Main features :
- Clean Markdown without js pollution : Layout injected from .astro files
- Free Path selection : can be placed anywhere within the repo
- Relative assets management : uses relative assets located in the same directory as the Markdown file
- Enhancement with Astro components : standard tags can be replaced with an Astro component without touching the Markdown files
- Modal Images and Gallery Components
- Nav Bar, Hierarchical menu, Table of Content with scroll spy,...
screenshot :
astro-home-control
- Github repo : https://github.com/MicroWebStacks/astro-home-control
Main features :
- Home Automation MQTT Client running on Astro as SSR
- Client page update with Server Sent Events
- Custom switches with feedback and custom sliders with animated SVG
screenshot :









