mirror of
https://github.com/cupcakearmy/nicco.io.git
synced 2025-09-06 02:30:45 +00:00
move to svelte kit
This commit is contained in:
99
src/app.css
Normal file
99
src/app.css
Normal file
@@ -0,0 +1,99 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Jost:wght@300;400&family=Playfair+Display&display=swap');
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
:root {
|
||||
--ff: 'Jost', Roboto, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans,
|
||||
Helvetica Neue, sans-serif;
|
||||
--ff-alt: 'Playfair Display', serif;
|
||||
--clr-light: #ffffff;
|
||||
--clr-dark: #010101;
|
||||
--clr-primary: hsl(219, 90%, 80%);
|
||||
--clr-secondary: hsl(64, 93%, 51%);
|
||||
--clr-error: hsl(0, 73.9%, 65.5%);
|
||||
--animation: all 250ms ease;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
|
||||
background-color: var(--clr-light);
|
||||
|
||||
font-family: var(--ff);
|
||||
font-size: 16px;
|
||||
font-weight: lighter;
|
||||
color: var(--clr-dark);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px;
|
||||
}
|
||||
|
||||
@media (min-width: 30em) {
|
||||
body {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: var(--ff-alt);
|
||||
font-weight: normal;
|
||||
margin: 1em 0 0.5em 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: justify;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0.1px solid var(--clr-primary);
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-left: 0px;
|
||||
padding-left: 1em;
|
||||
list-style: square;
|
||||
}
|
||||
|
||||
.progress {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
background: var(--clr-light);
|
||||
margin: 0.5em 0;
|
||||
padding: 0.1em 0.5em;
|
||||
border: 1px solid var(--clr-dark);
|
||||
}
|
||||
|
||||
.progress > span {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.progress > div {
|
||||
height: 100%;
|
||||
background: var(--clr-primary);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
}
|
@@ -4,35 +4,14 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="Designer & Developer" />
|
||||
<meta name="keywords" content="Web Agency Blog Articles" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,viewport-fit=cover"
|
||||
/>
|
||||
<meta name="theme-color" content="#333333" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover" />
|
||||
|
||||
%sapper.base%
|
||||
|
||||
<link rel="stylesheet" href="global.css" />
|
||||
<link rel="icon" type="image/png" href="/images/monogramm.png" />
|
||||
|
||||
<!-- Sapper generates a <style> tag containing critical CSS
|
||||
for the current page. CSS for the rest of the app is
|
||||
lazily loaded when it precaches secondary pages -->
|
||||
%sapper.styles%
|
||||
|
||||
<!-- This contains the contents of the <svelte:head> component, if
|
||||
the current page has one -->
|
||||
%sapper.head%
|
||||
%svelte.head%
|
||||
</head>
|
||||
<body>
|
||||
<!-- The application will be rendered inside this element,
|
||||
because `src/client.js` references it -->
|
||||
<div id="sapper">%sapper.html%</div>
|
||||
|
||||
<!-- Sapper creates a <script> tag containing `src/client.js`
|
||||
and anything else it needs to hydrate the app and
|
||||
initialise the router -->
|
||||
%sapper.scripts%
|
||||
<div id="svelte">%svelte.body%</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _paq = (window._paq = window._paq || [])
|
||||
@@ -56,11 +35,7 @@
|
||||
</script>
|
||||
<noscript
|
||||
><p>
|
||||
<img
|
||||
src="//stats.nicco.io/rainbow?idsite=1&rec=1"
|
||||
style="border: 0"
|
||||
alt=""
|
||||
/></p
|
||||
<img src="//stats.nicco.io/rainbow?idsite=1&rec=1" style="border: 0" alt="" /></p
|
||||
></noscript>
|
||||
</body>
|
||||
</html>
|
@@ -1,5 +0,0 @@
|
||||
import * as sapper from '@sapper/app';
|
||||
|
||||
sapper.start({
|
||||
target: document.querySelector('#sapper')
|
||||
});
|
@@ -1,61 +0,0 @@
|
||||
<script>
|
||||
import dj from 'dayjs'
|
||||
import ImageFrame from '../components/ImageFrame.svelte'
|
||||
import Icon from '../components/Icon.svelte'
|
||||
|
||||
export let work
|
||||
</script>
|
||||
|
||||
<a href={work.link} target="_blank" rel="noopener">
|
||||
<div class="horizontal">
|
||||
<div class="title regular">{work.title}</div>
|
||||
<div>
|
||||
<Icon icon="link-outline" />
|
||||
<span>{work.link.replace(/https?:\/\//, '')}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ImageFrame
|
||||
src={work.image.sizes.medium_large}
|
||||
alt={work.image.description}
|
||||
/>
|
||||
</a>
|
||||
<div class="horizontal regular">
|
||||
<div>{work.role}</div>
|
||||
<div>{dj(work.date * 1000).format('MMM YY')}</div>
|
||||
</div>
|
||||
<p>
|
||||
{@html work.content}
|
||||
</p>
|
||||
|
||||
<style>
|
||||
.title {
|
||||
font-size: 2em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.horizontal {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.regular {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 6em;
|
||||
}
|
||||
|
||||
a {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
@media (max-width: 30em) {
|
||||
.horizontal {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
</style>
|
1
src/global.d.ts
vendored
Normal file
1
src/global.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="@sveltejs/kit" />
|
52
src/lib/api/index.ts
Normal file
52
src/lib/api/index.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export const API = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_URL as string,
|
||||
})
|
||||
|
||||
export function gql(s: TemplateStringsArray) {
|
||||
return s.join('')
|
||||
}
|
||||
|
||||
export async function Call<T>(query: string, variables: Record<string, any> = {}): Promise<T> {
|
||||
const { data } = await API({
|
||||
url: '/graphql',
|
||||
method: 'post',
|
||||
data: {
|
||||
query,
|
||||
variables,
|
||||
},
|
||||
})
|
||||
return data.data as T
|
||||
}
|
||||
|
||||
export type Page = {
|
||||
title: string
|
||||
content: string | null
|
||||
slug: string
|
||||
id: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface Work extends Page {
|
||||
work: {
|
||||
date: string
|
||||
image: MediaItem
|
||||
link: string
|
||||
role: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface Project extends Page {
|
||||
project: {
|
||||
date: string
|
||||
link: string
|
||||
description: string
|
||||
}
|
||||
}
|
||||
|
||||
export type MediaItem = {
|
||||
srcSet: string
|
||||
altText: string
|
||||
sourceUrl: string
|
||||
}
|
@@ -1,13 +1,12 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
export let icon
|
||||
export let icon: string
|
||||
|
||||
$: src = `/icons/${icon}.svg`
|
||||
|
||||
let html = null
|
||||
let html: string | null = null
|
||||
|
||||
onMount(async () => {
|
||||
console.log(src)
|
||||
html = await fetch(src).then((res) => res.text())
|
||||
})
|
||||
</script>
|
||||
@@ -27,7 +26,6 @@
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
contain: strict;
|
||||
/* fill: currentcolor; */
|
||||
box-sizing: content-box;
|
||||
transform: translateY(0.2em);
|
||||
}
|
@@ -1,9 +1,15 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import Icon from './Icon.svelte'
|
||||
|
||||
export let links = []
|
||||
type Link = {
|
||||
href: string
|
||||
name: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
function isExternal(link) {
|
||||
export let links: Link[] = []
|
||||
|
||||
function isExternal(link: string) {
|
||||
return /^https?\:\/\//.test(link)
|
||||
}
|
||||
|
||||
@@ -15,11 +21,7 @@
|
||||
|
||||
<ul>
|
||||
{#each list as { href, name, icon, external }}
|
||||
<a
|
||||
rel={external ? 'noopener noreferrer' : ''}
|
||||
{href}
|
||||
target={external ? '_blank' : ''}
|
||||
>
|
||||
<a rel={external ? 'noopener noreferrer' : ''} {href} target={external ? '_blank' : ''}>
|
||||
<li>
|
||||
<Icon class="icon" {icon} />
|
||||
{name}
|
@@ -1,18 +1,22 @@
|
||||
<script context="module">
|
||||
<script lang="ts" context="module">
|
||||
import { initialize } from 'svelte-cloudinary'
|
||||
|
||||
initialize({ cloud_name: 'cupcakearmy' })
|
||||
</script>
|
||||
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { image } from 'svelte-cloudinary'
|
||||
|
||||
export let src
|
||||
export let alt
|
||||
export let src: string
|
||||
// export let srcset: string
|
||||
export let alt: string
|
||||
|
||||
$: cleaned = src.replace('https://api.nicco.io', '/nicco')
|
||||
</script>
|
||||
|
||||
<img use:image={{ src: cleaned, bind: { width: true }, lazy: true }} {alt} />
|
||||
|
||||
<!-- <img {srcset} {alt} /> -->
|
||||
<style>
|
||||
img {
|
||||
width: calc(100% - 0.25em);
|
||||
@@ -29,5 +33,3 @@
|
||||
margin: 1em 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<img use:image={{ src: cleaned, bind: { width: true }, lazy: true }} {alt} />
|
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import Icon from './Icon.svelte'
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores'
|
||||
|
||||
export let segment
|
||||
import Icon from './Icon.svelte'
|
||||
|
||||
const routes = [
|
||||
{ name: 'About', href: '/about' },
|
||||
@@ -11,12 +11,12 @@
|
||||
{ name: 'Contact', href: '/contact' },
|
||||
]
|
||||
|
||||
let nav
|
||||
let nav: HTMLDivElement
|
||||
</script>
|
||||
|
||||
<nav bind:this={nav}>
|
||||
<a href="/">
|
||||
<h1 class:active={segment === undefined}>NB</h1>
|
||||
<h1 class:active={$page.path === '/'}>NB</h1>
|
||||
</a>
|
||||
<ul>
|
||||
<li>
|
||||
@@ -28,7 +28,7 @@
|
||||
<li>
|
||||
<a {href}>
|
||||
<span>{name}</span>
|
||||
<div class:active={href.slice(1) === segment} />
|
||||
<div class:active={$page.path.startsWith(href)} />
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
@@ -1,19 +1,19 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import SpacedLetters from './SpacedLetters.svelte'
|
||||
|
||||
export let title = ''
|
||||
export let readable = false
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<h1>
|
||||
<SpacedLetters letters={title} {readable} />
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div {
|
||||
margin-top: calc(28vh - 3em);
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>
|
||||
<h1>
|
||||
<SpacedLetters letters={title} {readable} />
|
||||
</h1>
|
||||
</div>
|
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { spring } from 'svelte/motion'
|
||||
|
||||
import { scroll } from '../lib/scroll'
|
||||
import { scroll } from '$lib/stores'
|
||||
|
||||
let el
|
||||
const springed = spring(
|
||||
@@ -21,9 +21,7 @@
|
||||
const x = R + R * Math.cos(a) * 2
|
||||
const y = R - R * Math.sin(a) * 2
|
||||
const center = alpha > 180 ? 1 : 0
|
||||
const path = `M${R},${-50} A${R * 2},${
|
||||
R * 2
|
||||
},0,${center},1,${x},${y} L${R},${R} L${R},${-R}`
|
||||
const path = `M${R},${-50} A${R * 2},${R * 2},0,${center},1,${x},${y} L${R},${R} L${R},${-R}`
|
||||
if (el) el.setAttribute('d', path)
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
<script>
|
||||
import dj from 'dayjs'
|
||||
<script lang="ts">
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
import Icon from '../components/Icon.svelte'
|
||||
import Icon from './Icon.svelte'
|
||||
|
||||
export let project
|
||||
export let project: import('$lib/api').Project
|
||||
</script>
|
||||
|
||||
<section>
|
||||
<a href={project.link} target="_blank" rel="noopener">
|
||||
<a href={project.project.link} target="_blank" rel="noopener">
|
||||
<h2>{project.title}</h2>
|
||||
</a>
|
||||
<div class="subtitle">
|
||||
<b>{project.description}</b>
|
||||
<b class="date">{dj(project.date * 1000).format('MMM YY')}</b>
|
||||
<b>{project.project.description}</b>
|
||||
<b class="date">{dayjs(project.project.date, 'X').format('MMM YY')}</b>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
@@ -21,8 +21,8 @@
|
||||
|
||||
<div class="link">
|
||||
<Icon icon="link-outline" />
|
||||
<a rel="noopener noreferrer" target="_blank" href={project.link}
|
||||
>{project.link.replace(/https?:\/\//, '')}</a
|
||||
<a rel="noopener noreferrer" target="_blank" href={project.project.link}
|
||||
>{project.project.link.replace(/https?:\/\//, '')}</a
|
||||
>
|
||||
</div>
|
||||
</section>
|
@@ -1,4 +1,4 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import PageTitle from './PageTitle.svelte'
|
||||
|
||||
export let title = ''
|
||||
@@ -6,6 +6,12 @@
|
||||
export let readable = false
|
||||
</script>
|
||||
|
||||
<PageTitle {title} {readable} />
|
||||
|
||||
<section class:expanded>
|
||||
<slot />
|
||||
</section>
|
||||
|
||||
<style>
|
||||
section {
|
||||
max-width: 30em;
|
||||
@@ -16,9 +22,3 @@
|
||||
margin-top: 5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<PageTitle {title} {readable} />
|
||||
|
||||
<section class:expanded>
|
||||
<slot />
|
||||
</section>
|
@@ -1,9 +1,15 @@
|
||||
<script>
|
||||
export let letters = []
|
||||
<script lang="ts">
|
||||
export let letters: string = ''
|
||||
export let even = false
|
||||
export let readable = false
|
||||
</script>
|
||||
|
||||
<div class:even class:readable>
|
||||
{#if even}
|
||||
{#each letters as letter}<span>{letter}</span>{/each}
|
||||
{:else}{letters}{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
span {
|
||||
width: 1em;
|
||||
@@ -28,9 +34,3 @@
|
||||
font-size: 2.25rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class:even class:readable>
|
||||
{#if even}
|
||||
{#each letters as letter}<span>{letter}</span>{/each}
|
||||
{:else}{letters}{/if}
|
||||
</div>
|
@@ -1,4 +1,4 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import 'highlight.js/styles/github.css'
|
||||
import hljs from 'highlight.js/lib/core'
|
||||
import javascript from 'highlight.js/lib/languages/javascript'
|
||||
@@ -23,9 +23,9 @@
|
||||
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
export let content
|
||||
export let content: string
|
||||
|
||||
function encodeTextToUrl(text) {
|
||||
function encodeTextToUrl(text: string): string {
|
||||
return text
|
||||
.replace(/[^A-Za-z ]/, '')
|
||||
.replace('/ +/', ' ')
|
||||
@@ -35,14 +35,14 @@
|
||||
onMount(() => {
|
||||
hljs.highlightAll()
|
||||
|
||||
const selector = [1, 2, 3, 4, 5, 6]
|
||||
.map((i) => `div.adapter h${i}`)
|
||||
.join(', ')
|
||||
const selector = [1, 2, 3, 4, 5, 6].map((i) => `div.adapter h${i}`).join(', ')
|
||||
const elements = window.document.querySelectorAll(selector)
|
||||
for (const el of elements) {
|
||||
const hash = encodeTextToUrl(el.textContent)
|
||||
el.innerHTML = `<a class="target-link" name="${hash}" href="${window.location.pathname}#${hash}">${el.innerHTML}</a>`
|
||||
}
|
||||
elements.forEach((el) => {
|
||||
if (el.textContent) {
|
||||
const hash = encodeTextToUrl(el.textContent)
|
||||
el.innerHTML = `<a class="target-link" name="${hash}" href="${window.location.pathname}#${hash}">${el.innerHTML}</a>`
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
65
src/lib/components/Work.svelte
Normal file
65
src/lib/components/Work.svelte
Normal file
@@ -0,0 +1,65 @@
|
||||
<script lang="ts">
|
||||
import type { Work } from '$lib/api'
|
||||
import dayjs from 'dayjs'
|
||||
import ImageFrame from '$lib/components/ImageFrame.svelte'
|
||||
import Icon from '$lib/components/Icon.svelte'
|
||||
|
||||
export let work: Work
|
||||
</script>
|
||||
|
||||
<section>
|
||||
<a href={work.work.link} target="_blank" rel="noopener">
|
||||
<div class="horizontal">
|
||||
<div class="title regular">{work.title}</div>
|
||||
<div>
|
||||
<Icon icon="link-outline" />
|
||||
<span>{work.work.link.replace(/https?:\/\//, '')}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <ImageFrame src={work.work.image.sizes.medium_large} alt={work.image.description} /> -->
|
||||
<!-- <ImageFrame srcset={work.work.image.srcSet} alt={work.work.image.altText} /> -->
|
||||
<ImageFrame src={work.work.image.sourceUrl} alt={work.work.image.altText} />
|
||||
</a>
|
||||
<div class="horizontal regular">
|
||||
<div>{work.work.role}</div>
|
||||
<div>{dayjs(work.work.date, 'X').format('MMM YY')}</div>
|
||||
</div>
|
||||
{#if work.content}
|
||||
<p>
|
||||
{@html work.content}
|
||||
</p>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.title {
|
||||
font-size: 2em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.horizontal {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.regular {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
section {
|
||||
margin-bottom: 6em;
|
||||
}
|
||||
|
||||
a {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
@media (max-width: 30em) {
|
||||
.horizontal {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -1,6 +0,0 @@
|
||||
export function readingTimeInMinutes(text, options = {}) {
|
||||
options = Object.assign({ wpm: 200 }, options)
|
||||
const cleaned = text.replace(/(<.*?>)|(\\n)|(&#\d*?;)/g, '')
|
||||
const words = cleaned.split(' ').length
|
||||
return Math.round(words / options.wpm)
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
import axios from 'axios'
|
||||
|
||||
const isDev = process.env.NODE_ENV !== 'production' && false
|
||||
axios.defaults.baseURL = `${isDev ? 'http://localhost' : 'https://api.nicco.io'}/wp-json/wp/v2`
|
||||
|
||||
function normalize(post) {
|
||||
return {
|
||||
...post,
|
||||
...post.acf,
|
||||
id: post.id,
|
||||
title: post.title.rendered,
|
||||
content: post.content.rendered,
|
||||
}
|
||||
}
|
||||
|
||||
function combineUrlAndParams(url, params) {
|
||||
const p = new URLSearchParams({
|
||||
per_page: 100,
|
||||
...params,
|
||||
}).toString()
|
||||
return `${url}?${p}`
|
||||
}
|
||||
|
||||
export async function getOne(url, params = {}) {
|
||||
const { data } = await axios(combineUrlAndParams(url, params))
|
||||
if (!data.length) return null
|
||||
else return normalize(data[0])
|
||||
}
|
||||
|
||||
export async function getAll(url, params = {}) {
|
||||
const { data, headers } = await axios(combineUrlAndParams(url, params))
|
||||
const totalPages = parseInt(headers['x-wp-totalpages'])
|
||||
const results = [...data]
|
||||
if (totalPages > 1) {
|
||||
for (let page = 2; page <= totalPages; page++) {
|
||||
const { data } = await axios(combineUrlAndParams(url, { ...params, page }))
|
||||
results.push(...data)
|
||||
}
|
||||
}
|
||||
return results.map(normalize)
|
||||
}
|
||||
|
||||
export function sortByDate(data) {
|
||||
return data.sort((a, b) => parseInt(b.date) - parseInt(a.date))
|
||||
}
|
||||
|
||||
export function respond(res, body) {
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(JSON.stringify(body))
|
||||
}
|
@@ -1,22 +1,25 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
import { stores } from '@sapper/app'
|
||||
import { page } from '$app/stores'
|
||||
|
||||
import { scroll } from '../lib/scroll'
|
||||
import Nav from '../components/Nav.svelte'
|
||||
import Progress from '../components/Progress.svelte'
|
||||
import '../app.css'
|
||||
|
||||
export let segment
|
||||
let wrapper
|
||||
let main
|
||||
import dayjs from 'dayjs'
|
||||
import customParseFormat from 'dayjs/plugin/customParseFormat.js'
|
||||
dayjs.extend(customParseFormat)
|
||||
|
||||
import { scroll } from '$lib/stores'
|
||||
import Nav from '$lib/components/Nav.svelte'
|
||||
import Progress from '$lib/components/Progress.svelte'
|
||||
|
||||
let wrapper: HTMLDivElement
|
||||
let main: HTMLDivElement
|
||||
|
||||
function resize() {
|
||||
wrapper.style.height = `${window.innerHeight}px`
|
||||
}
|
||||
|
||||
const { page } = stores()
|
||||
let last = ''
|
||||
|
||||
$: {
|
||||
const { host, path } = $page
|
||||
const full = host + path
|
||||
@@ -26,25 +29,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
function updateScroll(e) {
|
||||
function updateScroll(e: any) {
|
||||
const el = e.target
|
||||
const percentage = el.scrollTop / (el.scrollHeight - el.offsetHeight)
|
||||
scroll.set(isNaN(percentage) ? 0 : percentage)
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
const resizeFN = window.addEventListener('resize', resize, false)
|
||||
const scrollFN = main.addEventListener('scroll', updateScroll, false)
|
||||
window.addEventListener('resize', resize, false)
|
||||
main.addEventListener('scroll', updateScroll, false)
|
||||
resize()
|
||||
return () => {
|
||||
window.removeEventListener(resizeFN)
|
||||
main.removeEventListener(scrollFN)
|
||||
window.removeEventListener('resize', resize)
|
||||
main.removeEventListener('scroll', updateScroll)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<div bind:this={wrapper}>
|
||||
<Nav {segment} />
|
||||
<Nav />
|
||||
<main bind:this={main}>
|
||||
<slot />
|
||||
</main>
|
@@ -1,28 +0,0 @@
|
||||
<script>
|
||||
export let status
|
||||
export let error
|
||||
|
||||
const dev = process.env.NODE_ENV === 'development'
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
font-size: 8vw;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1em auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:head>
|
||||
<title>{status}</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>{status}</h1>
|
||||
|
||||
<p>{error.message}</p>
|
||||
|
||||
{#if dev && error.stack}
|
||||
<pre>{error.stack}</pre>
|
||||
{/if}
|
@@ -1,16 +1,37 @@
|
||||
<script context="module">
|
||||
export async function preload() {
|
||||
return this.fetch('/api/pages/about.json').then((res) => res.json())
|
||||
<script lang="ts" context="module">
|
||||
import type { Load } from '@sveltejs/kit'
|
||||
|
||||
export const prerender = true
|
||||
export const load: Load = async ({ fetch }) => {
|
||||
return {
|
||||
props: {
|
||||
data: await fetch('/api/pages/about.json').then((r) => r.json()),
|
||||
image: await fetch('/api/media/about-2.json').then((r) => r.json()),
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import WPAdapter from '../components/WPAdapter.svelte'
|
||||
import SimplePage from '../components/SimplePage.svelte'
|
||||
<script lang="ts">
|
||||
import WPAdapter from '$lib/components/WPAdapter.svelte'
|
||||
import SimplePage from '$lib/components/SimplePage.svelte'
|
||||
import type { Page, MediaItem } from '$lib/api'
|
||||
|
||||
export let data
|
||||
export let data: Page
|
||||
export let image: MediaItem
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.title}</title>
|
||||
</svelte:head>
|
||||
|
||||
<SimplePage title={data.title} expanded={false}>
|
||||
{#if data.content}
|
||||
<WPAdapter content={data.content} />
|
||||
<img srcset={image.srcSet} alt="decoration" />
|
||||
{/if}
|
||||
</SimplePage>
|
||||
|
||||
<style>
|
||||
img {
|
||||
position: absolute;
|
||||
@@ -34,13 +55,3 @@
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:head>
|
||||
<title>About</title>
|
||||
</svelte:head>
|
||||
|
||||
<SimplePage title="About" expanded={false}>
|
||||
<WPAdapter content={data.content} />
|
||||
<!-- {@html data.content} -->
|
||||
<img src="/images/about.jpg" alt="decoration" />
|
||||
</SimplePage>
|
||||
|
@@ -1,13 +0,0 @@
|
||||
import { respond, getAll, getOne, sortByDate } from '../../lib/wp'
|
||||
|
||||
export async function get(req, res) {
|
||||
const [type, slug] = req.params.slug
|
||||
|
||||
if (slug) {
|
||||
const data = await getOne(type, { slug })
|
||||
respond(res, { data })
|
||||
} else {
|
||||
const data = await getAll(type)
|
||||
respond(res, { data: sortByDate(data) })
|
||||
}
|
||||
}
|
116
src/routes/api/[type]/[slug].json.ts
Normal file
116
src/routes/api/[type]/[slug].json.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import type { RequestHandler } from '@sveltejs/kit'
|
||||
|
||||
import { Call, gql, MediaItem, Page, Project } from '$lib/api'
|
||||
|
||||
export const get: RequestHandler = async (args) => {
|
||||
const { type, slug } = args.params
|
||||
const allChar = '*'
|
||||
const all = slug === allChar
|
||||
|
||||
switch (type) {
|
||||
case 'pages': {
|
||||
if (all) {
|
||||
const data = await Call<{ pages: { nodes: Page[] } }>(gql`
|
||||
query {
|
||||
pages {
|
||||
nodes {
|
||||
title
|
||||
content
|
||||
slug
|
||||
status
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
return { body: data.pages.nodes }
|
||||
} else {
|
||||
const data = await Call<{ page: Page }>(
|
||||
gql`
|
||||
query ($slug: ID!) {
|
||||
page(id: $slug, idType: URI) {
|
||||
title
|
||||
content
|
||||
slug
|
||||
status
|
||||
id
|
||||
}
|
||||
}
|
||||
`,
|
||||
{ slug: '/' + slug }
|
||||
)
|
||||
return { body: data.page }
|
||||
}
|
||||
}
|
||||
case 'works': {
|
||||
if (all) {
|
||||
const data = await Call<{ works: { nodes: MediaItem[] } }>(gql`
|
||||
query {
|
||||
works {
|
||||
nodes {
|
||||
id
|
||||
title
|
||||
content
|
||||
slug
|
||||
status
|
||||
work {
|
||||
date
|
||||
image {
|
||||
sourceUrl
|
||||
srcSet
|
||||
altText
|
||||
}
|
||||
link
|
||||
role
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
return { body: data.works.nodes }
|
||||
} else {
|
||||
}
|
||||
}
|
||||
case 'projects': {
|
||||
if (all) {
|
||||
const data = await Call<{ projects: { nodes: Project[] } }>(gql`
|
||||
query {
|
||||
projects {
|
||||
nodes {
|
||||
id
|
||||
title
|
||||
content
|
||||
slug
|
||||
status
|
||||
project {
|
||||
date
|
||||
description
|
||||
link
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
return { body: data.projects.nodes }
|
||||
}
|
||||
}
|
||||
|
||||
case 'media': {
|
||||
const data = await Call<{ mediaItem: MediaItem }>(
|
||||
gql`
|
||||
query ($slug: ID!) {
|
||||
mediaItem(id: $slug, idType: SLUG) {
|
||||
srcSet
|
||||
altText
|
||||
sourceUrl
|
||||
}
|
||||
}
|
||||
`,
|
||||
{ slug }
|
||||
)
|
||||
return { body: data.mediaItem }
|
||||
}
|
||||
default:
|
||||
return { status: 404 }
|
||||
}
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
<script context="module">
|
||||
export async function preload({ params }) {
|
||||
return this.fetch(`/api/posts/${params.slug}.json`).then((res) =>
|
||||
res.json()
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import SimplePage from '../../components/SimplePage.svelte'
|
||||
import WPAdapter from '../../components/WPAdapter.svelte'
|
||||
import PostAttributes from '../../components/PostAttributes.svelte'
|
||||
|
||||
export let data
|
||||
</script>
|
||||
|
||||
<SimplePage title={data.title} expanded={false} readable>
|
||||
<PostAttributes post={data} full />
|
||||
<WPAdapter content={data.content} />
|
||||
</SimplePage>
|
@@ -1,45 +0,0 @@
|
||||
<script context="module">
|
||||
export async function preload(page) {
|
||||
return this.fetch('/api/posts.json').then((res) => res.json())
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import SimplePage from '../../components/SimplePage.svelte'
|
||||
import PostPreview from '../../components/PostPreview.svelte'
|
||||
|
||||
export let data
|
||||
export let redirected = false
|
||||
|
||||
onMount(() => {
|
||||
redirected = new URL(location.href).searchParams.has('old')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div {
|
||||
margin-bottom: 6em;
|
||||
background-color: var(--clr-error);
|
||||
padding: 1em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:head>
|
||||
<title>Blog</title>
|
||||
</svelte:head>
|
||||
<SimplePage title="Blog">
|
||||
{#if redirected}
|
||||
<div>
|
||||
<h2>You have been redirected 🔄</h2>
|
||||
<p>
|
||||
Probably you are coming form my old blog (blog.nicco.io)
|
||||
<br />
|
||||
The article you were looking for is down here 👇
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
{#each data as post}
|
||||
<PostPreview {post} />
|
||||
{/each}
|
||||
</SimplePage>
|
@@ -1,7 +1,6 @@
|
||||
<script>
|
||||
import IconList from '../components/IconList.svelte'
|
||||
|
||||
import SimplePage from '../components/SimplePage.svelte'
|
||||
<script lang="ts">
|
||||
import IconList from '$lib/components/IconList.svelte'
|
||||
import SimplePage from '$lib/components/SimplePage.svelte'
|
||||
|
||||
const links = [
|
||||
{
|
||||
|
@@ -1,72 +1,111 @@
|
||||
<script>
|
||||
import SpacedLetters from '../components/SpacedLetters.svelte'
|
||||
<script lang="ts" context="module">
|
||||
import { Call, gql } from '$lib/api'
|
||||
|
||||
export const prerender = true
|
||||
|
||||
type Data = Record<'signature' | 'home', { srcSet: string }>
|
||||
export const load: Load = async () => {
|
||||
const data = await Call<Data>(gql`
|
||||
query {
|
||||
signature: mediaItem(id: "signature", idType: SLUG) {
|
||||
srcSet
|
||||
}
|
||||
|
||||
home: mediaItem(id: "home", idType: SLUG) {
|
||||
srcSet
|
||||
}
|
||||
}
|
||||
`)
|
||||
return { props: { data } }
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import SpacedLetters from '$lib/components/SpacedLetters.svelte'
|
||||
import type { Load } from '@sveltejs/kit'
|
||||
|
||||
export let data: Data
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Niccolo Borgioli</title>
|
||||
</svelte:head>
|
||||
|
||||
<section class="left" style="z-index: 3;">
|
||||
<h1>
|
||||
<SpacedLetters letters="Niccolò" even />
|
||||
<SpacedLetters letters="Borgioli" even />
|
||||
</h1>
|
||||
<div class="wrapper">
|
||||
<div class="left" style="z-index: 3;">
|
||||
<h1>
|
||||
<SpacedLetters letters="Niccolò" even />
|
||||
<SpacedLetters letters="Borgioli" even />
|
||||
</h1>
|
||||
|
||||
<p>Design & Development</p>
|
||||
</section>
|
||||
<p>Design & Development</p>
|
||||
</div>
|
||||
|
||||
<section class="right" style="z-index: 2;">
|
||||
<picture>
|
||||
<source media="(min-width: 60em)" srcset="/images/home@1500.webp" />
|
||||
<source media="(min-width: 45em)" srcset="/images/home@1000.webp" />
|
||||
<source srcset="/images/home@500.webp" />
|
||||
<img src="/images/decoration.jpg" alt="decoration" />
|
||||
</picture>
|
||||
</section>
|
||||
<div class="right" style="z-index: 2;">
|
||||
<img srcset={data.home.srcSet} alt="decoration" class="home" />
|
||||
<img srcset={data.signature.srcSet} alt="signature" class="signature" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
p {
|
||||
font-size: 4vw;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
section {
|
||||
.wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
section.left {
|
||||
align-items: flex-start;
|
||||
padding-left: 1em;
|
||||
width: initial;
|
||||
.left {
|
||||
flex: 1 0 auto;
|
||||
max-width: 64vw;
|
||||
}
|
||||
|
||||
section.right {
|
||||
align-items: flex-end;
|
||||
.right {
|
||||
position: relative;
|
||||
top: 5vh;
|
||||
}
|
||||
|
||||
img {
|
||||
p {
|
||||
font-size: 4vw;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
img.home {
|
||||
width: min(100%, 33vw);
|
||||
object-fit: contain;
|
||||
height: 65vh;
|
||||
width: 33vw;
|
||||
transform: translateY(5vh);
|
||||
object-position: left;
|
||||
max-height: 65vh;
|
||||
}
|
||||
img.signature {
|
||||
position: absolute;
|
||||
width: 50%;
|
||||
top: -6%;
|
||||
left: -10%;
|
||||
transform: rotate(-8deg);
|
||||
}
|
||||
|
||||
@media (max-width: 50em) {
|
||||
img {
|
||||
transform: translateY(15vh);
|
||||
height: 60vh;
|
||||
width: 69vw;
|
||||
.wrapper {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
section.left {
|
||||
transform: translateY(-25vh);
|
||||
.left {
|
||||
flex: initial;
|
||||
}
|
||||
|
||||
.right {
|
||||
left: 1rem;
|
||||
}
|
||||
|
||||
img.home {
|
||||
width: auto;
|
||||
height: 100%;
|
||||
max-height: calc(90vh - 35vw - 5vh);
|
||||
max-width: 90%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,16 +1,30 @@
|
||||
<script context="module">
|
||||
export async function preload() {
|
||||
return this.fetch('/api/pages/privacy.json').then((res) => res.json())
|
||||
<script lang="ts" context="module">
|
||||
import type { Load } from '@sveltejs/kit'
|
||||
|
||||
export const prerender = true
|
||||
export const load: Load = async ({ fetch }) => {
|
||||
return {
|
||||
props: {
|
||||
data: await fetch('/api/pages/privacy.json').then((r) => r.json()),
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import WPAdapter from '../components/WPAdapter.svelte'
|
||||
import SimplePage from '../components/SimplePage.svelte'
|
||||
<script lang="ts">
|
||||
import WPAdapter from '$lib/components/WPAdapter.svelte'
|
||||
import SimplePage from '$lib/components/SimplePage.svelte'
|
||||
import type { Page } from '$lib/api'
|
||||
|
||||
export let data
|
||||
export let data: Page
|
||||
</script>
|
||||
|
||||
<SimplePage title="Privacy Policy">
|
||||
<WPAdapter content={data.content} />
|
||||
<svelte:head>
|
||||
<title>{data.title}</title>
|
||||
</svelte:head>
|
||||
|
||||
<SimplePage title={data.title} expanded={false}>
|
||||
{#if data.content}
|
||||
<WPAdapter content={data.content} />
|
||||
{/if}
|
||||
</SimplePage>
|
||||
|
@@ -1,14 +1,21 @@
|
||||
<script context="module">
|
||||
export async function preload() {
|
||||
return this.fetch('/api/projects.json').then((res) => res.json())
|
||||
<script lang="ts" context="module">
|
||||
import type { Load } from '@sveltejs/kit'
|
||||
|
||||
export const load: Load = async ({ fetch }) => {
|
||||
return {
|
||||
props: {
|
||||
data: await fetch('/api/projects/*.json').then((r) => r.json()),
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import SimplePage from '../components/SimplePage.svelte'
|
||||
import Project from '../components/Project.svelte'
|
||||
import type { Project as TProject } from '$lib/api'
|
||||
import SimplePage from '$lib/components/SimplePage.svelte'
|
||||
import Project from '$lib/components/Project.svelte'
|
||||
|
||||
export let data
|
||||
export let data: TProject[]
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
@@ -1,34 +0,0 @@
|
||||
import lunr from 'lunr'
|
||||
|
||||
import { getAll } from '../lib/wp'
|
||||
|
||||
function removeHTML(s) {
|
||||
return s.replace(/<.*?>|\s+|&#\d+;/g, ' ').trim()
|
||||
}
|
||||
|
||||
async function convertForIdx(type, fields = []) {
|
||||
const items = await getAll(type)
|
||||
const keys = ['title', 'content', 'slug', ...fields]
|
||||
return items.map((item) => ({
|
||||
url: `${item.type}/${item.slug}`,
|
||||
data: keys.map((field) => removeHTML(item[field])).join(' '),
|
||||
}))
|
||||
}
|
||||
|
||||
export async function get(req, res) {
|
||||
const all = await Promise.all([
|
||||
convertForIdx('projects', ['description']),
|
||||
convertForIdx('pages'),
|
||||
convertForIdx('posts'),
|
||||
convertForIdx('works', ['role']),
|
||||
])
|
||||
|
||||
const idx = lunr(function () {
|
||||
this.ref('url')
|
||||
this.field('data')
|
||||
|
||||
all.flat().forEach((doc) => this.add(doc))
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(JSON.stringify(idx))
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
<script context="module">
|
||||
export async function preload({ query }) {
|
||||
const prebuilt = await this.fetch(`/search.json`).then((res) => res.json())
|
||||
return { prebuilt }
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import lunr from 'lunr'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
import SearchResult from '../components/SearchResult.svelte'
|
||||
import SimplePage from '../components/SimplePage.svelte'
|
||||
|
||||
export let prebuilt
|
||||
let needle
|
||||
let results = []
|
||||
|
||||
const idx = lunr.Index.load(prebuilt)
|
||||
|
||||
async function search(needle) {
|
||||
if (!needle || !idx) {
|
||||
results = []
|
||||
} else {
|
||||
let found = idx.search(needle + '~1')
|
||||
if (!found.length) found = idx.search(needle + '*')
|
||||
results = found.slice(0, 20)
|
||||
}
|
||||
}
|
||||
|
||||
$: if (needle) {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.history.replaceState(null, null, `/search?q=${needle || ''}`)
|
||||
}
|
||||
search(needle)
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
needle = new URLSearchParams(window.location.search).get('q')
|
||||
})
|
||||
</script>
|
||||
|
||||
<SimplePage title="Search" expanded={false}>
|
||||
<input bind:value={needle} placeholder="needle" />
|
||||
<ul>
|
||||
{#each results as result (result.ref)}
|
||||
<SearchResult {result} />
|
||||
{/each}
|
||||
</ul>
|
||||
</SimplePage>
|
||||
|
||||
<style>
|
||||
input {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
padding: 0.5rem;
|
||||
font-size: 1em;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
border: 2px solid var(--clr-primary);
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 2em;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
@@ -1,7 +1,6 @@
|
||||
<script>
|
||||
import IconList from '../components/IconList.svelte'
|
||||
|
||||
import SimplePage from '../components/SimplePage.svelte'
|
||||
<script lang="ts">
|
||||
import IconList from '$lib/components/IconList.svelte'
|
||||
import SimplePage from '$lib/components/SimplePage.svelte'
|
||||
|
||||
const links = [
|
||||
{
|
||||
|
@@ -1,14 +1,21 @@
|
||||
<script context="module">
|
||||
export async function preload() {
|
||||
return this.fetch('/api/works.json').then((res) => res.json())
|
||||
<script lang="ts" context="module">
|
||||
import type { Load } from '@sveltejs/kit'
|
||||
|
||||
export const load: Load = async ({ fetch }) => {
|
||||
return {
|
||||
props: {
|
||||
data: await fetch('/api/works/*.json').then((r) => r.json()),
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import SimplePage from '../components/SimplePage.svelte'
|
||||
import Work from '../components/Work.svelte'
|
||||
<script lang="ts">
|
||||
import type { Work as TWork } from '$lib/api'
|
||||
import SimplePage from '$lib/components/SimplePage.svelte'
|
||||
import Work from '$lib/components/Work.svelte'
|
||||
|
||||
export let data
|
||||
export let data: TWork[]
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
@@ -1,15 +0,0 @@
|
||||
import sirv from 'sirv'
|
||||
import polka from 'polka'
|
||||
import compression from 'compression'
|
||||
import * as sapper from '@sapper/server'
|
||||
|
||||
const { PORT, NODE_ENV } = process.env
|
||||
const dev = NODE_ENV === 'development'
|
||||
|
||||
polka()
|
||||
.use(compression({ threshold: 0 }))
|
||||
.use(sirv('static', { dev }))
|
||||
.use(sapper.middleware())
|
||||
.listen(PORT, (err) => {
|
||||
if (err) console.log('error', err)
|
||||
})
|
Reference in New Issue
Block a user