Skip to content

Commit

Permalink
Copy Template Repo
Browse files Browse the repository at this point in the history
root committed Dec 31, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
0 parents commit f4bf17e
Showing 35 changed files with 9,570 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: 2
updates:
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'daily'
allow:
- dependency-name: '@edgio/*'
open-pull-requests-limit: 10
19 changes: 19 additions & 0 deletions .github/workflows/layer0.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Deploy to Edgio

on:
workflow_dispatch:
push:

jobs:
deploy-to-layer0:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: 14
registry-url: https://npm-proxy.fury.io/moovweb/
- run: npm ci
- run: npm run edgio:deploy -- --token=$LAYER0_DEPLOY_TOKEN
env:
LAYER0_DEPLOY_TOKEN: ${{secrets.LAYER0_DEPLOY_TOKEN}}
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# build output
/dist
/.layer0
/.edgio

# dependencies
/node_modules

# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*


# environment variables
.env
.env.production

# macOS-specific files
.DS_Store

# vs-code specific files
/.vscode

sw/bundled-service-worker.js
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Expose Astro dependencies for `pnpm` users
shamefully-hoist=true
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/.layer0
/.vscode
/dist
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Deploy Astro SSR example to Edgio

A demo deployment of Astro SSR app to Edgio.

## Demo

https://layer0-docs-layer0-astro-ssr-example-default.layer0-limelight.link

## Try It Now

[![Deploy with Edgio](https://docs.edg.io/button.svg)](https://app.layer0.co/deploy?repo=https://github.com/edgio-docs/edgio-astro-ssr-example)

## Getting Started

### Clone This Repo

Use `git clone https://github.com/edgio-docs/edgio-astro-ssr-example.git` to get the files within this repository onto your local machine.

### Install dependencies

On the command line, in the project root directory, run the following command:

```bash
npm install
```

### Run the Astro app locally on Edgio

Run the Astro app with the command:

```bash
npm run edgio:dev
```

Load the site: http://127.0.0.1:3000

### Testing production build locally with Edgio

You can do a production build of your app and test it locally using:

```bash
npm run edgio:build && npm run edgio:production
```

Setting --production runs your app exactly as it will be uploaded to the Edgio cloud using serverless-offline.

## Deploying to Edgio

Deploying requires an account on Edgio. [Sign up here for free](https://app.layer0.co/signup). Once you have an account, you can deploy to Edgio by running the following in the root folder of your project:

```bash
npm run edgio:deploy
```

See [deploying](https://docs.edg.io/guides/deploying) for more information.
14 changes: 14 additions & 0 deletions astro.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import react from '@astrojs/react'
import tailwind from '@astrojs/tailwind'
import { defineConfig } from 'astro/config'

import node from '@astrojs/node'

// https://astro.build/config
export default defineConfig({
integrations: [react(), tailwind()],
output: 'server',
adapter: node({
mode: 'standalone',
}),
})
15 changes: 15 additions & 0 deletions buildServiceWorker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const esbuild = require('esbuild')

const appDir = process.cwd()

esbuild.buildSync({
entryPoints: [`${appDir}/sw/service-worker.js`],
outfile: `${appDir}/sw/bundled-service-worker.js`,
minify: true,
bundle: true,
define: {
'process.env.NODE_ENV': '"production"',
'process.env.EDGIO_PREFETCH_HEADER_VALUE': '"1"',
'process.env.EDGIO_PREFETCH_CACHE_NAME': '"prefetch"',
},
})
66 changes: 66 additions & 0 deletions cache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
export const PAGE_CACHE_HANDLER = ({ cache }) => {
cache({
edge: {
maxAgeSeconds: 60,
},
})
}

export const API_CACHE_HANDLER = ({ cache, proxy }) => {
cache({
edge: {
maxAgeSeconds: 60 * 60,
// Cache responses even if they contain cache-control: private header
// https://docs.edg.io/guides/caching#private
// https://docs.edg.io/docs/api/core/interfaces/_router_cacheoptions_.edgecacheoptions.html#forceprivatecaching
forcePrivateCaching: true,
},
browser: {
// Don't save the response in the browser
maxAgeSeconds: 0,
// Save the response in the browser via Edgio service worker
serviceWorkerSeconds: 60 * 60 * 24,
},
})
proxy('api', { path: ':path*' })
}

export const IMAGE_CACHE_HANDLER = ({ cache, proxy }) => {
cache({
edge: {
maxAgeSeconds: 60 * 60,
// Cache responses even if they contain cache-control: private header
// https://docs.edg.io/guides/caching#private
// https://docs.edg.io/docs/api/core/interfaces/_router_cacheoptions_.edgecacheoptions.html#forceprivatecaching
forcePrivateCaching: true,
},
browser: {
// Don't save the response in the browser
maxAgeSeconds: 0,
// Save the response in the browser via Edgio service worker
serviceWorkerSeconds: 60 * 60 * 24,
},
})
proxy('image', { path: '/' })
}

export const ASSET_CACHE_HANDLER = ({ removeUpstreamResponseHeader, cache }) => {
// Remove the cache-control header coming in from the Next.js app,
// and remove the set-cookie header coming in from the Next.js app,
// this is to ensure that the response is cacheable
removeUpstreamResponseHeader('set-cookie')
removeUpstreamResponseHeader('cache-control')
// Set the caching values
cache({
edge: {
// Save the response(s) [whether stale or updated] in the edge POP for a year
maxAgeSeconds: 60 * 60 * 24 * 365,
},
browser: {
// Don't save the response in the browser
maxAgeSeconds: 0,
// Save the response in the browser via Edgio service worker
serviceWorkerSeconds: 60 * 60 * 24,
},
})
}
23 changes: 23 additions & 0 deletions edgio.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module.exports = {
connector: '@edgio/astro',
astro: {
appPath: './dist/server/entry.mjs',
},
backends: {
// Define a domain or IP address to proxy as a backend
// More on: https://docs.edg.io/guides/edgio_config#backends
api: {
domainOrIp: 'layer0-docs-layer0-ecommmerce-api-example-default.layer0-limelight.link',
hostHeader: 'layer0-docs-layer0-ecommmerce-api-example-default.layer0-limelight.link',
// Disable backend SSL certificate security check, read more on:
// https://docs.edg.io/guides/edgio_config#:~:text=browser%20is%20used.-,disableCheckCert,-Boolean
disableCheckCert: true,
},
// More on: https://docs.edg.io/guides/image_optimization
image: {
domainOrIp: 'opt.moovweb.net',
hostHeader: 'opt.moovweb.net',
disableCheckCert: true,
},
},
}
8,772 changes: 8,772 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "layer0-astro-ssr-example",
"scripts": {
"astro": "astro",
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"edgio:dev": "node buildServiceWorker.js && edgio dev",
"edgio:build": "node buildServiceWorker.js && edgio build",
"edgio:deploy": "node buildServiceWorker.js && edgio deploy",
"edgio:production": "edgio run --production",
"format": "prettier --write '**/*' --ignore-unknown"
},
"dependencies": {
"@astrojs/node": "latest",
"@types/react": "^17.0.50",
"@types/react-dom": "^17.0.17",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"@astrojs/react": "latest",
"@astrojs/tailwind": "latest",
"@edgio/astro": "^5.0.4",
"@edgio/cli": "^5.0.4",
"@edgio/core": "^5.0.4",
"@edgio/devtools": "^5.0.4",
"@edgio/prefetch": "^5.0.4",
"@edgio/react": "^5.0.4",
"@heroicons/react": "^1.0.6",
"astro": "latest",
"classnames": "^2.3.1",
"prettier": "^2.7.1",
"prettier-plugin-astro": "latest",
"tailwindcss": "^3.2.1"
}
}
6 changes: 6 additions & 0 deletions prettier.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
semi: false,
singleQuote: true,
printWidth: 150,
plugins: [require('prettier-plugin-astro')],
}
12 changes: 12 additions & 0 deletions public/__edgio__/client/rum.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
function initMetrics() {
new Layer0.Metrics({
token: '4793b50d-db03-43a2-9584-c971e06a6c88',
}).collect()
}

var rumScriptTag = document.createElement('script')
rumScriptTag.src = 'https://rum.layer0.co/latest.js'
rumScriptTag.setAttribute('defer', '')
rumScriptTag.type = 'text/javascript'
rumScriptTag.onload = initMetrics
document.body.appendChild(rumScriptTag)
10 changes: 10 additions & 0 deletions public/logo/white.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions public/styles/product.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.product-thumbnails::-webkit-scrollbar {
display: none;
}
.product-thumbnails {
-ms-overflow-style: none;
scrollbar-width: none;
}
22 changes: 22 additions & 0 deletions routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// This file was automatically added by edgio deploy.
// You should commit this file to source control.

import { Router } from '@edgio/core'
import { astroRoutes } from '@edgio/astro'

import { PAGE_CACHE_HANDLER, API_CACHE_HANDLER, IMAGE_CACHE_HANDLER } from './cache'

export default new Router()
// Prevent search engines from indexing permalink URLs
.noIndexPermalink()
.match('/service-worker.js', ({ serviceWorker }) => {
serviceWorker('sw/bundled-service-worker.js')
})
.match('/', PAGE_CACHE_HANDLER)
.match('/about', PAGE_CACHE_HANDLER)
.match('/commerce', PAGE_CACHE_HANDLER)
.match('/commerce/:path*', PAGE_CACHE_HANDLER)
.match('/product/:path*', PAGE_CACHE_HANDLER)
.match('/l0-api/:path*', API_CACHE_HANDLER)
.match('/l0-opt', IMAGE_CACHE_HANDLER)
.use(astroRoutes)
32 changes: 32 additions & 0 deletions src/components/About.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react'

const About = ({ showcases }) => {
return (
<div className="flex min-h-[calc(100vh-56px)] flex-col items-center px-5 md:px-0">
<div className="mt-10 flex w-full max-w-2xl flex-col p-2.5">
<span className="text-2xl font-semibold text-white">About</span>
<span className="mt-5 text-lg text-[#FFFFFF75]">This demo of Edgio showcases the following:</span>
<ul className="list-disc">
{showcases.map((i) => (
<li key={i} className="mt-3 text-[#FFFFFF75]">
{i}
</li>
))}
</ul>
<div className="mt-5 flex flex-row items-center space-x-3 text-lg text-[#FFFFFF90]">
<svg className="h-[15px] w-[15px] md:h-[25px] md:w-[25px]" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z" />
</svg>
<a target="_blank" className="border-b border-[#FFFFFF75] text-sm md:text-lg" href="https://github.com/edgio-docs/edgio-astro-ssr-example">
edgio-docs/edgio-astro-ssr-example
</a>
</div>
<a className="mt-5" target="_blank" href="https://app.layer0.co/deploy?repo=https://github.com/edgio-docs/edgio-astro-ssr-example">
<img height="15px" src="https://docs.edg.io/button.svg" />
</a>
</div>
</div>
)
}

export default About
30 changes: 30 additions & 0 deletions src/components/Commerce.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { filterProducts } from '@/helper'
import Sidebar from '@/components/Sidebar'
import React, { useEffect, useState } from 'react'
import ProductPreview from '@/components/ProductPreview'

const Commerce = ({ data }) => {
const [filter, setFilter] = useState(undefined)
useEffect(() => {
setFilter(new URLSearchParams(window.location.search).get('filter'))
}, [])
return (
<div className="flex-col items-center justify-start">
<div className="flex w-full flex-row items-start px-5">
<div className="flex min-w-[200px] flex-col pt-5">
<Sidebar />
</div>
<div className="flex flex-col items-start pt-5">
<h2 className="text-[#FFFFFF75]">Showing {data.length} Results</h2>
<div className="sm:grid-cols-2 mt-5 grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6">
{filterProducts(data, filter).map((i) => (
<ProductPreview key={i.path} {...i} />
))}
</div>
</div>
</div>
</div>
)
}

export default Commerce
45 changes: 45 additions & 0 deletions src/components/Home.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react'

const Home = () => {
return (
<div className="flex min-h-[calc(100vh-56px)] flex-col items-center justify-center px-5 md:px-0">
<div className="flex w-full flex-row flex-wrap justify-center md:w-[700px]">
<div className="flex w-[330px] flex-col items-start justify-start rounded p-5 md:w-1/2">
<h1 className="text-xl font-bold text-white">Astro SSR with Edgio</h1>
<h3 className="mt-2 text-lg text-[#FFFFFF75]">Edgio supports all of the most powerful features of Astro SSR!</h3>
<a className="mt-auto text-[#01B18D] hover:underline" href="https://docs.edg.io/guides/astro#example-ssr-site" target="_blank">
Learn More &rarr;
</a>
</div>
<div className="flex w-[330px] flex-col items-start justify-start rounded p-5 md:w-1/2">
<h1 className="text-xl font-bold text-white">Astro with Edgio</h1>
<h3 className="mt-2 text-lg text-[#FFFFFF75]">Edgio supports all of the most powerful features of Astro!</h3>
<a className="mt-auto text-[#01B18D] hover:underline" href="https://docs.edg.io/guides/astro" target="_blank">
Learn More &rarr;
</a>
</div>
<div className="flex w-[330px] flex-col items-start justify-start rounded p-5 md:w-1/2">
<h1 className="text-xl font-bold text-white">Caching with Edgio</h1>
<h3 className="mt-2 mb-5 text-lg text-[#FFFFFF75]">
While most CDNs only cache content on your asset URLs, Edgio caches content on your page URLs using EdgeJS, allowing you to control
caching within your application code.
</h3>
<a className="mt-auto text-[#01B18D] hover:underline" href="https://docs.edg.io/guides/caching" target="_blank">
Learn More &rarr;
</a>
</div>
<div className="flex w-[330px] flex-col items-start justify-start rounded p-5 md:w-1/2">
<h1 className="text-xl font-bold text-white">Edgio Prefetching</h1>
<h3 className="mt-2 text-lg text-[#FFFFFF75]">
Edgio allows you to speed up the user’s browsing experience by prefetching pages and API calls that they are likely to need.
</h3>
<a className="mt-auto text-[#01B18D] hover:underline" href="https://docs.edg.io/guides/prefetching" target="_blank">
Learn More &rarr;
</a>
</div>
</div>
</div>
)
}

export default Home
40 changes: 40 additions & 0 deletions src/components/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react'
import { useEffect } from 'react'
import { Prefetch } from '@edgio/react'
import { install } from '@edgio/prefetch/window'
import installDevtools from '@edgio/devtools/install'

const Navbar = () => {
useEffect(() => {
install()
installDevtools()
}, [])
return (
<div className="flex flex-row flex-wrap items-center justify-between py-3 px-5">
<a href="/">
<Prefetch url="/">
<img src="/logo/white.svg" className="h-[25px] w-[60.2px] bg-white/5" />
</Prefetch>
</a>
<div className="flex flex-row items-center space-x-4 py-1">
<Prefetch url="/about">
<a href="/about" className="text-[#FFFFFF75]">
About
</a>
</Prefetch>
<Prefetch url="/commerce">
<a href="/commerce" className="text-[#FFFFFF75]">
Commerce
</a>
</Prefetch>
<a href="https://github.com/edgio-docs/edgio-astro-ssr-example" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" className="fill-[#FFFFFF75]" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z" />
</svg>
</a>
</div>
</div>
)
}

export default Navbar
54 changes: 54 additions & 0 deletions src/components/Product.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react'
import { relativizeURL } from '@/helper'
import { StarIcon } from '@heroicons/react/solid/esm/index.js'
import { HeartIcon, StarIcon as StarIconOutline } from '@heroicons/react/outline/esm/index.js'

const Product = ({ data }) => {
return (
<div className="flex w-full flex-col items-center">
<div className="pb-12 flex max-w-6xl flex-col lg:flex-row">
<div className="relative flex w-full flex-col items-start lg:w-1/2">
<div className="absolute top-0 left-0 z-10 flex flex-col items-start">
<h3 className="border border-gray-200 bg-white py-2 px-4 text-2xl font-bold text-black">{data.name}</h3>
<h4 className="border border-gray-200 bg-white py-2 px-4 text-lg text-black">{`$ ${data.prices.price.value} ${data.prices.price.currencyCode}`}</h4>
</div>
<HeartIcon className="absolute top-0 right-0 z-10 h-[50px] w-[50px] border border-gray-200 bg-white p-2" />
<div className="flex w-full flex-col items-center">
<img src={relativizeURL(data.images[0].url)} className="h-auto w-full max-w-[600px]" />
</div>
<div className="product-thumbnails mt-5 flex flex-row items-start gap-x-2 overflow-x-scroll">
{data.images.map((i, ind) => (
<img key={i.url} loading="lazy" src={relativizeURL(i.url)} className="h-[250px] w-auto hover:bg-white" />
))}
</div>
</div>
<div className="flex w-full flex-col items-start px-10 lg:w-1/2">
<h1 className="mt-10 text-3xl font-bold text-white lg:mt-0">{data.name}</h1>
<h2 dangerouslySetInnerHTML={{ __html: data.description }} className="text-md mt-5 font-light text-[#FFFFFF75]"></h2>
<div className="mt-10 flex w-full flex-row justify-between">
<div className="flex flex-row items-center space-x-1">
<StarIcon className="h-[20px] w-[20px] text-[#FFFFFF75]" />
<StarIcon className="h-[20px] w-[20px] text-[#FFFFFF75]" />
<StarIcon className="h-[20px] w-[20px] text-[#FFFFFF75]" />
<StarIcon className="h-[20px] w-[20px] text-[#FFFFFF75]" />
<StarIconOutline className="h-[18px] w-[18px] text-[#FFFFFF75]" />
</div>
<span className="text-[#FFFFFF75]">36 reviews</span>
</div>
<button className="mt-5 w-full bg-black px-2 py-4 uppercase text-white">Add To Cart</button>
<span className="mt-5 text-lg font-medium text-white">Care</span>
<span className="mt-2 font-light text-[#FFFFFF75]">This is a limited edition production run. Printing starts when the drop ends.</span>
<div className="mt-5 h-[1px] w-full bg-[#FFFFFF30]"></div>
<span className="mt-5 text-lg font-medium text-white">Details</span>
<span className="mt-2 font-light text-[#FFFFFF75]">
This is a limited edition production run. Printing starts when the drop ends. Reminder: Bad Boys For Life. Shipping may take 10+ days due
to COVID-19.
</span>
<div className="mt-5 h-[1px] w-full bg-[#FFFFFF30]"></div>
</div>
</div>
</div>
)
}

export default Product
21 changes: 21 additions & 0 deletions src/components/ProductPreview.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'
import { Prefetch } from '@edgio/react'
import { relativizeURL } from '@/helper'
import { HeartIcon } from '@heroicons/react/outline/esm/index.js'

const ProductPreview = ({ name, slug, images, prices }) => {
return (
<a href={`/product/${slug}`} className="relative mt-2 border border-white p-1">
<div className="absolute top-0 left-0 z-10 flex flex-col items-start">
<h3 className="border border-gray-200 bg-white py-1 px-2 text-xs font-medium text-black md:py-2 md:px-4 md:text-xl">{name}</h3>
<h4 className="border border-gray-200 bg-white py-1 px-2 text-xs text-black md:py-2 md:px-4 md:text-lg">{`${prices.price.value}${prices.price.currencyCode}`}</h4>
</div>
<Prefetch url={`/product/${slug}`}>
<HeartIcon className="absolute top-0 right-0 h-[30px] w-[30px] bg-white p-2" />
</Prefetch>
<img className="h-full bg-white object-contain" loading="lazy" width={1200} height={1200} src={relativizeURL(images[0].url)} />
</a>
)
}

export default ProductPreview
81 changes: 81 additions & 0 deletions src/components/Sidebar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import classNames from 'classnames'
import React, { useEffect, useState } from 'react'

const relevanceItems = [
{
name: 'Trending',
filter: 'trending',
},
{
name: 'Price: Low to High',
filter: 'price-low-to-high',
},
{
name: 'Price: High to Low',
filter: 'price-high-to-low',
},
]

const Sidebar = () => {
const [filter, setFilter] = useState(undefined)
const [listingItems, setListingItems] = useState([])
const [pathWithoutQuery, setPathWithoutQuery] = useState(undefined)
useEffect(() => {
setPathWithoutQuery(window.location.pathname)
setFilter(new URLSearchParams(window.location.search).get('filter'))
fetch('/l0-api/categories/all')
.then((res) => res.json())
.then((res) => {
setListingItems(res)
})
}, [])
return (
<div className="flex w-full flex-col">
<h2 className="text-md font-light text-[#FFFFFF75]">Relevance</h2>
{relevanceItems.map((item) => (
<a
key={item.name}
className={classNames(
'text-md mt-2 cursor-pointer',
{ 'font-light text-[#FFFFFF75]': filter !== item.filter },
{ 'font-medium text-[#FFFFFF]': filter === item.filter }
)}
onClick={(e) => {
e.preventDefault()
if (typeof window !== undefined) {
const url = new URL(window.location)
url.searchParams.set('filter', item.filter)
window.location.href = url
}
}}
>
{item.name}
</a>
))}
<a
href={`/commerce`}
className={classNames(
'text-md mt-7',
{ 'font-light text-[#FFFFFF75]': pathWithoutQuery !== `/commerce` },
{ 'font-medium text-[#FFFFFF]': pathWithoutQuery === `/commerce` }
)}
>
Shop All
</a>
{listingItems.map((item) => (
<a
href={`/commerce/${item.slug}`}
className={classNames(
'text-md mt-2',
{ 'font-light text-[#FFFFFF75]': pathWithoutQuery !== `/commerce/${item.slug}` },
{ 'font-medium text-[#FFFFFF]': pathWithoutQuery === `/commerce/${item.slug}` }
)}
>
{item.name}
</a>
))}
</div>
)
}

export default Sidebar
39 changes: 39 additions & 0 deletions src/helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export const relativizeURL = (str) =>
str.replace(
'https://layer0-docs-layer0-ecommmerce-api-example-default.layer0-limelight.link/',
'/l0-opt?quality=30&img=https://layer0-docs-layer0-ecommmerce-api-example-default.layer0-limelight.link/'
)

export const filterProducts = (data, filter) => {
let temp = data
if (filter) {
if (filter === 'trending') {
temp.sort((a, b) => (Math.random() > 0.5 ? 1 : -1))
} else if (filter === 'price-low-to-high') {
temp.sort((a, b) => (a.price.value > b.price.value ? 1 : -1))
} else if (filter === 'price-high-to-low') {
temp.sort((a, b) => (a.price.value > b.price.value ? -1 : 1))
}
}
return temp
}

export const getOrigin = (req) => {
let origin
if (typeof window !== 'undefined') {
origin = window.location.origin
}
if (req) {
let hostURL = req.headers['host']
if (hostURL) {
hostURL = hostURL.replace('http://', '')
hostURL = hostURL.replace('https://', '')
if (hostURL.includes('localhost:') || hostURL.includes('127.0.0.1')) {
origin = `http://${hostURL}`
} else {
origin = `https://${hostURL}`
}
}
}
return origin
}
19 changes: 19 additions & 0 deletions src/layouts/MainLayout.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
import Navbar from '@/components/Navbar'
---

<html lang="en" class="initial">
<head>
<meta charset="utf-8" />
<meta name="generator" content={Astro.generator} />
<meta name="viewport" content="width=device-width" />
</head>

<body class="font-display flex min-h-screen flex-col bg-gradient-to-br from-[#9a1ab1] via-[#004966] to-[#01B18D]">
<Navbar client:load />
<slot />
<script is:inline defer src="/__edgio__/client/rum.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" />
<link rel="stylesheet" href="/styles/product.css" />
</body>
</html>
9 changes: 9 additions & 0 deletions src/pages/about.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
import About from '@/components/About'
import { showcases } from '@/showcases'
import MainLayout from '@/layouts/MainLayout.astro'
---

<MainLayout>
<About showcases={showcases} />
</MainLayout>
14 changes: 14 additions & 0 deletions src/pages/commerce.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
import { getOrigin } from '@/helper'
import Commerce from '@/components/Commerce'
import MainLayout from '@/layouts/MainLayout.astro'
const host = Astro.request.headers.get('host')
const origin = getOrigin({ headers: { host } })
const resp = await fetch(`${origin}/l0-api/products/all`)
const data = await resp.json()
---

<MainLayout>
<Commerce client:load data={data} />
</MainLayout>
15 changes: 15 additions & 0 deletions src/pages/commerce/[name].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
import { getOrigin } from '@/helper'
import Commerce from '@/components/Commerce'
import MainLayout from '@/layouts/MainLayout.astro'
const host = Astro.request.headers.get('host')
const origin = getOrigin({ headers: { host } })
const { name } = Astro.params
const resp = await fetch(`${origin}/l0-api/categories/${name}`)
const data = (await resp.json())['items']
---

<MainLayout>
<Commerce client:load data={data} />
</MainLayout>
8 changes: 8 additions & 0 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
import Home from '@/components/Home'
import MainLayout from '@/layouts/MainLayout.astro'
---

<MainLayout>
<Home />
</MainLayout>
15 changes: 15 additions & 0 deletions src/pages/product/[name].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
import { getOrigin } from '@/helper'
import Product from '@/components/Product'
import MainLayout from '@/layouts/MainLayout.astro'
const host = Astro.request.headers.get('host')
const origin = getOrigin({ headers: { host } })
const { name } = Astro.params
const resp = await fetch(`${origin}/l0-api/products/${name}`)
const data = await resp.json()
---

<MainLayout>
<Product data={data} />
</MainLayout>
10 changes: 10 additions & 0 deletions src/showcases.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const showcases = [
`Edgio's Compatbility with Astro`,
'Static Pre-rendering with Edgio, to warm cache as soon as the app goes to production (or the cache is cleared)',
'(Free) Real Time User Monitoring service offered by Edgio',
'(Free) Edgio Image Optimization Service',
'Edge and Browser caching of SSR page(s)',
'Prefetching with Edgio Service Worker to speeden up transitions',
'Proxying and Caching external API(s) for faster edge and browser responses',
'Edgio Devtools: See what came from the edge, browser and serverless',
]
9 changes: 9 additions & 0 deletions sw/service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Prefetcher } from '@edgio/prefetch/sw'
import { precacheAndRoute } from 'workbox-precaching'
import { skipWaiting, clientsClaim } from 'workbox-core'

skipWaiting()
clientsClaim()
precacheAndRoute(self.__WB_MANIFEST || [])

new Prefetcher().route()
14 changes: 14 additions & 0 deletions tailwind.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const { fontFamily } = require('tailwindcss/defaultTheme')

/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {
fontFamily: {
display: ['Inter', ...fontFamily.sans],
},
},
},
plugins: [],
}
16 changes: 16 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"jsx": "react-jsx",
"jsxImportSource": "react"
}
}

0 comments on commit f4bf17e

Please sign in to comment.