Commit 896a71d2 by PLN

Merge branch 'feat/v0.2' into 'main'

Feat/v0.2

See merge request !1
parents 1454cd7b 1fd386d1
# Content # Content
- Pro - Pro
- Landing page: projects with links
- Talks - Talks
- Hydra - Detail page?
- ParVagues - IMG!
- Hydra[id]: Render own source
- ParVagues: Generic landing with master player, a code sample, and subpages
- Details page per item: fetch source-code, fetch song
# Customization # Customization
- Image de profil: neural or bust!
- General style - General style
- Favicon - Favicon
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
This is a starter template for [Learn Next.js](https://nextjs.org/learn).
\ No newline at end of file
import Image from 'next/image'
function Avatar() {
return <Image src="/images/me.png" alt="me" width="64" height="64" />
}
export default Avatar
import styles from './Button.module.css'
export function Button() {
return (
<button
type="button"
className={styles.error}
>
Destroy
</button>
)
}
.error {
color: white;
background-color: red;
}
import { parseISO, format } from 'date-fns'
export default function Date({ dateString, dateFormat }) {
const date = parseISO(dateString)
const finalFormat = dateFormat || 'LLLL d, yyyy'
return <time dateTime={dateString}>{format(date, finalFormat)}</time>
}
import React, { useRef, useEffect } from "react";
class HydraSynth extends React.Component {
constructor(props) {
super(props);
this.width = props.width;
this.height = props.height;
this.source= props.source;
}
componentDidMount() {
const Hydra = require('hydra-synth');
const hydra = new Hydra({
// canvas element to render to. If none is supplied, a canvas will be created and appended to the screen
// canvas: this.canvasRef,
autoLoop: true,
makeGlobal: true,
numSources: 4,
detectAudio: false,
numOutputs: 4,
});
hydra.setResolution(this.width, this.height);
//TODO: Use source
// FIXME: Canvas position
s0.initImage("https://git.plnech.fr/pln/Hydra/raw/master/StarryNights/img/halley.png");
src(s0).out(o0)
src(o0)
.modulate(src(o0),() => Math.sin(time/100) / 10)
.out(o1)
src(o1)
.modulateScale(osc(1,0.4),0.05)
.blend(noise(100,0.92).colorama(),0.07)
.out(o2)
src(o2)
.blend(src(o2).thresh(), () => 0.5 + 0.125 * Math.sin(time / 100 % 180))
.scrollX(-0.05)
// .scrollY(-0.1)
.scale(1.08)
.out(o3)
render(o3)
}
render() {
return <canvas ref="{this.canvasRef}" width={this.width} height={this.height} />;
}
}
export default HydraSynth
import Head from 'next/head'
import Image from 'next/image'
import styles from './layout.module.css'
import utilStyles from '../styles/utils.module.css'
import Link from 'next/link'
const name = 'PLN'
export const siteTitle = 'PLN\'s Works'
export default function Layout({ children, home }) {
return (
<div className={styles.container}>
<Head>
<link rel="icon" href="/favicon.ico" />
<meta
name="description"
content="PLN's Selected Works"
/>
<meta
property="og:image"
content={`https://og-image.vercel.app/${encodeURI(
siteTitle
)}.png?theme=dark&md=0&fontSize=75px&images=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fnextjs-black-logo.svg`}
/>
<meta name="og:title" content={siteTitle} />
<meta name="twitter:card" content="summary_large_image" />
</Head>
<header className={styles.header}>
{home ? (
<>
<Image
priority
src="/images/profile.png"
className={utilStyles.borderCircle}
height={144}
width={144}
alt={name}
/>
<h1 className={utilStyles.heading2Xl}>{name}</h1>
</>
) : (
<>
<Link href="/">
<a>
<Image
priority
src="/images/profile.png"
className={utilStyles.borderCircle}
height={108}
width={108}
alt={name}
/>
</a>
</Link>
<h2 className={utilStyles.headingLg}>
<Link href="/">
<a className={utilStyles.colorInherit}>{name}</a>
</Link>
</h2>
</>
)}
</header>
<main>{children}</main>
{!home && (
<div className={styles.backToHome}>
<Link href="/">
<a> Back to home</a>
</Link>
</div>
)}
<footer>
PLN 2021 | <a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
></a>
</footer>
</div>
)
}
.container {
max-width: 42rem;
padding: 0 1rem;
margin: 3rem auto 6rem;
}
.header {
display: flex;
flex-direction: column;
align-items: center;
}
.backToHome {
margin: 3rem 0 0;
}
---
title: Dusty Halley
source: https://git.plnech.fr/pln/Hydra/raw/master/StarryNights/DustyHalley.js
---
---
title: Ariane13
source: https://git.plnech.fr/pln/Hydra/raw/master/StarryNights/Ariane13.js
---
---
title: GaLactic
source: https://git.plnech.fr/pln/Hydra/raw/master/StarryNights/GaLactic.js
---
---
title: Hello World
date: '2021-04-23'
---
> _C'est un petit pas pour l'homme, mais un grand pas pour le serverless._
**Ceci n'est pas un premier post.**
---
title: NextJs Tutorial
date: '2021-04-23'
---
Gotta say the [Vercel Next.JS Tutorial](https://nextjs.org/learn/basics/create-nextjs-app) was a delight to follow.
A couple hours and this site is live. :)
---
title: Coopérer avec d'autres métiers
description: "Retour d'expérience sur l'iGEM et la coopération entre ingénieurs, biologistes, et designers."
date: "2020-04-21"
org: Université Rennes1
context: Remise de diplômes 2020 du Master BioInfo Rennes1
video: https://nech.pl/bigday2020-video
slides: https://nech.pl/bigday2020
event: https://bioinfo-fr.net/big-day-2020
---
https://www.youtube.com/watch?v=un0cFiN65yg
---
title: 'Having a Voice on Mobile: How hard can it be?'
description: "Many mobile apps add voice commands. When does it actually help?"
date: '2019-11-02'
context: Droidcon London 2019
video: https://nech.pl/droidcon19-video
slides: https://nech.pl/droidcon19
event: https://skillsmatter.com/conferences/11785-droidcon-london-2019
---
---
title: The Musicologist, or Search as a Conversation
description: "How NLP APIs and modern mobile ecosystems let us build search experiences as natural language conversations."
date: '2017-11-27'
slides: https://www.slideshare.net/PaulLouisNECH/search-as-a-conversation-paris-nlp-meetup
video: https://www.youtube.com/watch?v=3eb4KMNcOII
context: ParisNLP Meetup
event: https://twitter.com/ParisNLP/status/933416243964628992
---
---
title: Mobile Search Patterns
context: 4 Years From Now
org: Mobile World Congress
date: '2017-02-28'
slides: https://docs.google.com/presentation/d/1tHvU26nKkabHbHBomXgeSzjuVr9juJPcckKvUcdneRk/edit?usp=sharing
event: https://www.4yfn.com/
---
---
title: Build search on any platform
context: Zenika Nightclazz
date: '2017-03-02'
event: https://www.meetup.com/fr-FR/NightClazz-Lille-by-Zenika/
slides: https://fr.slideshare.net/mobile/PaulLouisNECH/atelier-algolia-zenika-lille
---
---
title: A tale of two APIs
description: "How leveraging two APIs (DialogFlow and Algolia) allows to transform a JSON file describing a couple hundreds songs into an interactive, conversational experience."
date: '2018-01-23'
context: ParisAPI#31
event: https://www.meetup.com/ParisAPI/events/246453990/
slides: https://drive.google.com/file/d/1-bzpJUjlVRhQJSLjUQJbe3AFg4mS3RoN/view?usp=sharing
---
---
title: Serving Humans? Ethics and Politics of Technological Design
description: 'In our era of services, *who* is being served by technologies?'
context: 'Humanities After Humans: Our Extended Bodies, Ourselves'
org: Université de Lorraine, INHA, UCP
date: '2020-12-11'
video: https://nech.pl/serving-humans-video
slides: https://nech.pl/serving-humans
event: https://humanitiesafterhumans.wordpress.com/
---
---
title: Workshop | The Challenges of Conversational Search
description: "Introduction to using Algolia APIs to power your voice experience, with a focus on fast prototyping."
date: '2018-06-15'
event: http://talktome.berlin/
context: TalkToMe! Berlin Hackathon
slides: https://docs.google.com/presentation/d/1ofZ17FZsmUyRu5_10-ndpKAQMJ_3m_e0tA5ZXDVFp-k/edit?usp=sharing
video: https://www.youtube.com/watch?v=_U-K9oaNBhc
---
import {getAllContentData, getAllContentIds, getContentData} from './utils'
export function getHydrasData() {
return getAllContentData('hydras', true)
}
export function getAllHydraIds() {
return getAllContentIds("hydras")
}
export async function getHydraData(id) {
return getContentData("hydras", id)
}
import {getAllContentData, getAllContentIds, getContentData} from './utils'
export function getPostsData() {
return getAllContentData('posts', true)
}
export function getAllPostIds() {
return getAllContentIds("posts")
}
export async function getPostData(id) {
return getContentData("posts", id)
}
import {getAllContentData, getAllContentIds, getContentData} from './utils'
export function getTalksData() {
return getAllContentData('talks', true)
}
export function getRecentTalksData() {
return getAllContentData('talks', true).slice(0,3)
}
export function getAllTalkIds() {
return getAllContentIds("talks")
}
export async function getTalkData(id) {
return getContentData("talks", id)
}
import path from "path";
import fs from "fs";
import matter from "gray-matter";
import remark from "remark";
import html from "remark-html";
function getContentDirectory(name) {
return path.join(process.cwd(), "content", name)
}
function getAllContentData(name, sorted = false) {
// Get file names under /content/{name}
const contentDirectory = getContentDirectory(name);
const fileNames = fs.readdirSync(contentDirectory);
console.log(`gACD: total ${name}(s): ${fileNames.length}`);
const allContentData = fileNames.map((fileName) => {
// Remove ".md" from file name to get id
const id = fileName.replace(/\.md$/, "");
// Read markdown file as string
const fullPath = path.join(contentDirectory, fileName);
const fileContents = fs.readFileSync(fullPath, "utf8");
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents);
// Combine the data with the id
return {
id,
...matterResult.data,
};
});
return sorted
? allContentData.sort((a, b) => {
if (a.date < b.date) {
return 1;
} else {
return -1;
}
})
: allContentData;
}
function getAllContentIds(name) {
const fileNames = fs.readdirSync(getContentDirectory(name));
console.log(`getAllContentIds: ${fileNames.length} ${name}(s).`);
return fileNames.map((fileName) => {
return {
params: {
id: fileName.replace(/\.md$/, ""),
},
};
});
}
async function getContentData(name, id) {
const fullPath = path.join(getContentDirectory(name), `${id}.md`);
console.log("Got content fullPath:", fullPath);
const fileContents = fs.readFileSync(fullPath, "utf8");
console.log("Got contents:", fileContents);
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents);
// Use remark to convert markdown into HTML string
const processedContent = await remark()
.use(html)
.process(matterResult.content);
const contentHtml = processedContent.toString();
console.log(matterResult);
if ("description" in matterResult.data) {
console.log("Got desc!");
const processedDescription = await remark()
.use(html)
.process(matterResult.data.description);
matterResult.data.description = processedContent.toString();
}
// Combine the data with the id and contentHtml
return {
id,
contentHtml,
...matterResult.data,
};
}
export {
getContentDirectory,
getContentData,
getAllContentData,
getAllContentIds,
};
/// <reference types="next" />
{
"name": "pln-www",
"version": "0.2.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"engines": {
"node": "==12"
},
"dependencies": {
"bootstrap": "^5.0.0-beta3",
"classnames": "^2.3.1",
"date-fns": "^2.21.1",
"gray-matter": "^4.0.2",
"hydra-synth": "^1.3.8",
"next": "^10.1.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-player": "^2.9.0",
"react-syntax-highlighter": "^15.4.3",
"remark": "^13.0.0",
"remark-html": "^13.0.1"
},
"devDependencies": {
"@types/react": "^17.0.3",
"typescript": "^4.2.4"
}
}
import 'bootstrap/dist/css/bootstrap.css'
import '../styles/main.css'
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
import Image from "next/image";
import Link from "next/link";
import Head from "next/head";
import Layout from "../components/layout";
import HydraSynth from "../components/hydra";
import utilStyles from "../styles/utils.module.css";
import { getHydrasData } from "../lib/hydras";
export async function getStaticProps() {
const hydras = getHydrasData();
return {
props: {
hydras,
},
};
}
export default function Hydra({hydras}) {
return (
<Layout className="hydra">
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>PLN's Hydra works</title>
</Head>
<div>
<h1>I create visuals with patterns</h1>
<Image
alt="GaLactic intermediary steps"
src="/images/WIP_GaLactic.png"
// layout="fill"
width={700}
height={475}
/>
<p>
<i>
Successive layers within the work{" "}
<a href="https://nech.pl/nights-galactic">GaLactic</a>,
part of the serie <b>Nuits étoilées</b><br />in which I turn pictures of the night sky into animated windows on the universe.
</i>
</p>
<br />
<h2>Some works</h2>
<ul className={utilStyles.list}>
{hydras.map(
({
id,
title,
}) => (
<li className={utilStyles.listItem} key={id}>
<Link href={`/hydra/${id}`}><h4> {title}</h4></Link>
</li>
)
)}
</ul>
</div>
</Layout>
);
}
import SyntaxHighlighter from "react-syntax-highlighter";
import Head from "next/head";
import Layout from "../../components/layout";
import HydraSynth from "../../components/hydra";
import Date from "../../components/date";
const https = require("https");
import utilStyles from "../../styles/utils.module.css";
import { getAllHydraIds, getHydraData } from "../../lib/hydras";
export async function getStaticProps({ params }) {
const hydraData = await getHydraData(params.id);
const response = await fetch(hydraData.source);
const source = await response.text();
const sourceCode = source.replace(/(?:\r\n|\r|\n)/g, "<br>");
hydraData.source = source;
return {
props: {
hydraData,
sourceCode,
},
};
}
export async function getStaticPaths() {
const paths = getAllHydraIds();
return {
paths,
fallback: false,
};
}
export default function Hydra({ hydraData, sourceCode }) {
return (
<Layout>
<Head>
<title>{hydraData.title}</title>
</Head>
<article>
<h1 className={utilStyles.headingXl}>{hydraData.title}</h1>
<SyntaxHighlighter
width="64em"
language="javascript"
wrapLongLines={true}
>
{hydraData.source}
</SyntaxHighlighter>
{/*<HydraSynth
width={700}
height={475}
source={hydraData.source}/>*/}
</article>
</Layout>
);
}
import Head from "next/head";
import Link from "next/link";
import Date from "../components/date";
import Layout from "../components/layout";
import utilStyles from "../styles/utils.module.css";
import { getPostsData } from "../lib/posts";
import { getRecentTalksData } from "../lib/talks";
export async function getStaticProps() {
const nbLastTalks = 3;
const talks = getRecentTalksData();
const posts = getPostsData();
return {
props: {
posts,
talks,
},
};
}
export default function Home({ posts, talks }) {
return (
<div className="container">
<Layout home>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>PLN's Home</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<section className={utilStyles.headingMd}>
<h1 className="title">Bienvenue !</h1>
<h2>
I'm PLN, and I love to <i>transform</i>
</h2>
<h3>
code into <em>solutions to human problems</em>
</h3>
<p className="description">
At <a href="https://algolia.com">Algolia</a>, I create technologies
to help humans find things and
<a href="https://www.algolia.com/products/answers-for-support/">
{" "}
answers
</a>
.
</p>
<h3>
code into <em>music</em>
</h3>
<p className="description">
As <Link href="/parvagues/">ParVagues</Link>, I write patterns that
shape soundwaves.
</p>
<h3>
code into <em>animated pixelscapes</em>
</h3>
<p className="description">
Using <Link href="/hydra/">Hydra</Link>, I create animations that
offer windows into other words.
</p>
</section>
<section className={`${utilStyles.headingMd} ${utilStyles.padding1px}`}>
<h3>
ideas into <em>talks</em>
</h3>
<p className="description">
I <Link href="/talks/">speak</Link> about topics I care about: from
sharing my passions and teaching useful patterns, to questioning our
current mental models.
</p>
<h2 className={utilStyles.headingLg}>Most recent talks</h2>
<ul className={utilStyles.list}>
{talks.map(({ id, title, description }) => (
<li className={utilStyles.listItem} key={id}>
<Link href={`/talk/${id}`} key={id}>
<h4>{title}</h4>
</Link>
{description && (
<small className={utilStyles.lightText}>{description}</small>
)}
<br />
</li>
))}
</ul>
</section>
<section className={`${utilStyles.headingMd} ${utilStyles.padding1px}`}>
<h2 className={utilStyles.headingLg}>Blog</h2>
<ul className={utilStyles.list}>
{posts.map(({ id, date, title }) => (
<li className={utilStyles.listItem} key={id}>
<Link href={`/post/${id}`}>
<a>{title}</a>
</Link>
<br />
<small className={utilStyles.lightText}>
<Date dateString={date} />
</small>
</li>
))}
</ul>
</section>
</Layout>
</div>
);
}
import Image from "next/image";
import Link from "next/link";
import Head from "next/head";
import Layout from "../components/layout";
import utilStyles from "../styles/utils.module.css";
import SyntaxHighlighter from "react-syntax-highlighter";
import React from "react";
import ReactPlayer from "react-player";
export async function getStaticProps(context) {
const tidalSampleUrl = "https://git.plnech.fr/pln/Tidal/raw/f5bfbc74e68dcaac0f6afa93f2b47d35321274c8/live/dnb/automne_electrique.tidal"
const response = await fetch(tidalSampleUrl);
const source = await response.text();
// Remove working title
const sourceClean = source.split("\n").slice(1).join("\n")
return {
props: {
urlSC: "https://soundcloud.com/parvagues/",
urlTwitch: "https://twitch.tv/parvagues/",
urlTwitchExample: "https://www.twitch.tv/videos/965233250",
urlAutomne: "https://soundcloud.com/parvagues/automne-electrique",
tidalSample: sourceClean
},
};
}
export default function ParVagues({
urlSC,
urlTwitch,
urlTwitchExample,
tidalSample,
}) {
return (
<Layout>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>ParVagues</title>
</Head>
<div>
<section className={utilStyles.headingMd}>
<h1>I create music with patterns</h1>
<h4>
<i>
ParVagues, c'est des ondes sonores qui naissent dans un océan
binaire pour parfois s'échouer sur vos plages sonores.
</i>
</h4>
{/*<Image
alt="ParVagues performing"
src="/images/ParVagues.jpg"
layout="fill"
width={700}
height={475}
/>*/}
</section>
<section className={utilStyles.headingMd}>
<h5>
A source sample: the code behind <a href="">Automne Électrique</a>:
</h5>
<SyntaxHighlighter
className="source-code"
width="64em"
language="haskell"
wrapLines={true}
>
{tidalSample}
</SyntaxHighlighter>
</section>
<section className={utilStyles.headingMd}>
<h4>
I sometimes post recordings on <a href={urlSC}>SoundCloud</a>
</h4>
<div className="player-wrapper">
<ReactPlayer
className="react-player"
url={urlSC}
width="100%"
height="32em"
/>
</div>
</section>
<section className={utilStyles.headingMd}>
<h4>
I sometimes do live performances on <a href={urlTwitch}>Twitch</a>
</h4>
<div className="player-wrapper">
<ReactPlayer
className="react-player"
url={urlTwitchExample}
width="100%"
height="32em"
/>
</div>
</section>
</div>
</Layout>
);
}
import Head from "next/head";
import Layout from "../../components/layout";
import Date from "../../components/date";
import utilStyles from "../../styles/utils.module.css";
import { getAllPostIds, getPostData } from "../../lib/posts";
export async function getStaticProps({ params }) {
const postData = await getPostData(params.id);
return {
props: {
postData,
},
};
}
export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
}
export default function Post({ postData }) {
return (
<Layout>
<Head>
<title>{postData.title}</title>
</Head>
<article>
<h1 className={utilStyles.headingXl}>{postData.title}</h1>
<div className={utilStyles.lightText}>
<Date dateString={postData.date} />
</div>
<div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} />
</article>
</Layout>
);
}
import Image from "next/image";
import Link from "next/link";
import Head from "next/head";
import Layout from "../components/layout";
import utilStyles from "../styles/utils.module.css";
import { getTalksData } from "../lib/talks";
import React from "react";
import ReactPlayer from "react-player";
export async function getStaticProps() {
const talks = getTalksData();
const selection = [];
return {
props: {
talks,
selection,
},
};
}
export default function Talks({ talks, selection }) {
return (
<Layout>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Talks</title>
</Head>
<div>
<section className={utilStyles.headingMd}>
<h1>I speak about topics I love</h1>
<ul>
{selection.map(({}) => (
<li>
<h3>Item</h3>
</li>
))}
</ul>
</section>
<ul className={utilStyles.list}>
{talks.map(
({
id,
title,
description,
date,
org,
context,
video,
slides,
event,
}) => (
<li className={utilStyles.listItem} key={id}>
<h3>{title}</h3>
{description && (
<>
<small>{description}</small>
<br />
</>
)}
<small className={utilStyles.lightText}>
<Date dateString={date} />
{context && (
<p>
{" "}
<i>
at <a href={event}>{context}</a>{" "}
{org && <>organised by {org}</>}
</i>
</p>
)}
</small>{" "}
<ul class="links">
{video && (
<li>
<a href={video}>Video</a>
</li>
)}
{slides && (
<li>
<a href={slides}>Slides</a>
</li>
)}
{event && (
<li>
<a href={event}>Event</a>
</li>
)}
</ul>
</li>
)
)}
</ul>
</div>
</Layout>
);
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="1.16em" height="1em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 222"><path d="M128 0l128 221.705H0z" fill="#000"/></svg>
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
line-height: 1.6;
font-size: 18px;
}
* {
box-sizing: border-box;
}
a {
color: #0070f3;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
img {
max-width: 100%;
display: block;
}
header {
margin-bottom: 2em;
}
main h2 {
margin-bottom: 1em;
}
main h3 {
/* margin: 1em 0; */
}
h4 {
font-size: 1.2rem;
}
ul.links {
margin-bottom: 3em;
}
p.code {
font-family: monospace;
}
section {
margin-bottom: 4em;
}
small {
font-size: 1rem;
}
footer {
margin-top: 4em;
text-align: center;
color: #228;
}
h1 a, h2 a, h3 a, h4 a, h5 a {
text-decoration: underline;
}
.source-code {
max-height: 36em;
}
.player-wrapper {
padding: 12em 0;
position: relative;
padding-top: 56.25% /* Player ratio: 100 / (1280 / 720) */
}
.react-player {
position: absolute;
top: 0;
left: 0;
}
.heading2Xl {
font-size: 2.5rem;
line-height: 1.2;
font-weight: 800;
letter-spacing: -0.05rem;
margin: 1rem 0;
}
.headingXl {
font-size: 2rem;
line-height: 1.3;
font-weight: 800;
letter-spacing: -0.05rem;
margin: 1rem 0;
}
.headingLg {
font-size: 1.5rem;
line-height: 1.4;
margin: 1rem 0;
}
.headingMd {
font-size: 1.2rem;
line-height: 1.5;
}
.borderCircle {
border-radius: 9999px;
}
.colorInherit {
color: inherit;
}
.padding1px {
padding-top: 1px;
}
.list {
list-style: none;
padding: 0;
margin: 0;
}
.listItem {
margin: 0 0 1.25rem;
}
.lightText {
color: #666;
}
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"dependencies": {
"gatsby-cli": "^3.3.0"
}
}
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# dotenv environment variable files
.env*
# gatsby files
.cache/
public
# Mac files
.DS_Store
# Yarn
yarn-error.log
.pnp/
.pnp.js
# Yarn Integrity file
.yarn-integrity
.cache
package.json
package-lock.json
public
{
"arrowParens": "avoid",
"semi": false
}
The BSD Zero Clause License (0BSD)
Copyright (c) 2020 Gatsby Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
<!-- AUTO-GENERATED-CONTENT:START (STARTER) -->
<p align="center">
<a href="https://www.gatsbyjs.com">
<img alt="Gatsby" src="https://www.gatsbyjs.com/Gatsby-Monogram.svg" width="60" />
</a>
</p>
<h1 align="center">
Gatsby's default starter
</h1>
Kick off your project with this default boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React.
_Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.com/docs/gatsby-starters/)._
## 🚀 Quick start
1. **Create a Gatsby site.**
Use the Gatsby CLI to create a new site, specifying the default starter.
```shell
# create a new Gatsby site using the default starter
gatsby new my-default-starter https://github.com/gatsbyjs/gatsby-starter-default
```
1. **Start developing.**
Navigate into your new site’s directory and start it up.
```shell
cd my-default-starter/
gatsby develop
```
1. **Open the source code and start editing!**
Your site is now running at `http://localhost:8000`!
_Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.com/tutorial/part-five/#introducing-graphiql)._
Open the `my-default-starter` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time!
## 🚀 Quick start (Gatsby Cloud)
Deploy this starter with one click on [Gatsby Cloud](https://www.gatsbyjs.com/cloud/):
[<img src="https://www.gatsbyjs.com/deploynow.svg" alt="Deploy to Gatsby Cloud">](https://www.gatsbyjs.com/dashboard/deploynow?url=https://github.com/gatsbyjs/gatsby-starter-default)
## 🧐 What's inside?
A quick look at the top-level files and directories you'll see in a Gatsby project.
.
├── node_modules
├── src
├── .gitignore
├── .prettierrc
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
├── gatsby-ssr.js
├── LICENSE
├── package-lock.json
├── package.json
└── README.md
1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed.
2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”.
3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for.
4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent.
5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.com/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser.
6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.com/docs/gatsby-config/) for more detail).
7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.com/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process.
8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.com/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering.
9. **`LICENSE`**: This Gatsby starter is licensed under the 0BSD license. This means that you can see this file as a placeholder and replace it with your own license.
10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).**
11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project.
12. **`README.md`**: A text file containing useful reference information about your project.
## 🎓 Learning Gatsby
Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.com/). Here are some places to start:
- **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.com/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process.
- **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.com/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar.
## 💫 Deploy
[Build, Deploy, and Host On The Only Cloud Built For Gatsby](https://www.gatsbyjs.com/cloud/)
Gatsby Cloud is an end-to-end cloud platform specifically built for the Gatsby framework that combines a modern developer experience with an optimized, global edge network.
<!-- AUTO-GENERATED-CONTENT:END -->
/**
* Implement Gatsby's Browser APIs in this file.
*
* See: https://www.gatsbyjs.com/docs/browser-apis/
*/
// You can delete this file if you're not using it
module.exports = {
siteMetadata: {
title: `PLN`,
description: `A brief introduction to my work.`,
author: `@PaulLouisNech`,
},
plugins: [
`gatsby-plugin-react-helmet`,
`gatsby-plugin-image`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
},
},
`gatsby-plugin-gatsby-cloud`,
// this (optional) plugin enables Progressive Web App + Offline functionality
// To learn more, visit: https://gatsby.dev/offline
// `gatsby-plugin-offline`,
],
}
/**
* Implement Gatsby's Node APIs in this file.
*
* See: https://www.gatsbyjs.com/docs/node-apis/
*/
// You can delete this file if you're not using it
/**
* Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
*
* See: https://www.gatsbyjs.com/docs/ssr-apis/
*/
// You can delete this file if you're not using it
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "gatsby-starter-default",
"private": true,
"description": "A simple starter to get up and developing quickly with Gatsby",
"version": "0.1.0",
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
"dependencies": {
"gatsby": "^3.3.1",
"gatsby-plugin-gatsby-cloud": "^2.2.0",
"gatsby-plugin-image": "^1.2.1",
"gatsby-plugin-manifest": "^3.2.0",
"gatsby-plugin-offline": "^4.2.0",
"gatsby-plugin-react-helmet": "^4.2.0",
"gatsby-plugin-sharp": "^3.2.1",
"gatsby-source-filesystem": "^3.2.0",
"gatsby-transformer-sharp": "^3.2.0",
"prop-types": "^15.7.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-helmet": "^6.1.0"
},
"devDependencies": {
"prettier": "2.2.1"
},
"keywords": [
"gatsby"
],
"license": "0BSD",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
"start": "npm run develop",
"serve": "gatsby serve",
"clean": "gatsby clean",
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-default"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
}
}
import * as React from "react"
import PropTypes from "prop-types"
import { Link } from "gatsby"
const Header = ({ siteTitle }) => (
<header
style={{
background: `rebeccapurple`,
marginBottom: `1.45rem`,
}}
>
<div
style={{
margin: `0 auto`,
maxWidth: 960,
padding: `1.45rem 1.0875rem`,
}}
>
<h1 style={{ margin: 0 }}>
<Link
to="/"
style={{
color: `white`,
textDecoration: `none`,
}}
>
{siteTitle}
</Link>
</h1>
</div>
</header>
)
Header.propTypes = {
siteTitle: PropTypes.string,
}
Header.defaultProps = {
siteTitle: ``,
}
export default Header
html {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
font: 112.5%/1.45em georgia, serif, sans-serif;
box-sizing: border-box;
overflow-y: scroll;
}
body {
margin: 0;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: hsla(0, 0%, 0%, 0.8);
font-family: georgia, serif;
font-weight: normal;
word-wrap: break-word;
font-kerning: normal;
-moz-font-feature-settings: "kern", "liga", "clig", "calt";
-ms-font-feature-settings: "kern", "liga", "clig", "calt";
-webkit-font-feature-settings: "kern", "liga", "clig", "calt";
font-feature-settings: "kern", "liga", "clig", "calt";
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
main,
menu,
nav,
section,
summary {
display: block;
}
audio,
canvas,
progress,
video {
display: inline-block;
}
audio:not([controls]) {
display: none;
height: 0;
}
progress {
vertical-align: baseline;
}
[hidden],
template {
display: none;
}
a {
background-color: transparent;
-webkit-text-decoration-skip: objects;
}
a:active,
a:hover {
outline-width: 0;
}
abbr[title] {
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
cursor: help;
text-decoration: none;
}
b,
strong {
font-weight: inherit;
font-weight: bolder;
}
dfn {
font-style: italic;
}
h1 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 2.25rem;
line-height: 1.1;
}
mark {
background-color: #ff0;
color: #000;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
img {
border-style: none;
max-width: 100%;
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
svg:not(:root) {
overflow: hidden;
}
code,
kbd,
pre,
samp {
font-family: monospace;
font-size: 1em;
}
figure {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
hr {
box-sizing: content-box;
overflow: visible;
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: calc(1.45rem - 1px);
background: hsla(0, 0%, 0%, 0.2);
border: none;
height: 1px;
}
button,
input,
optgroup,
select,
textarea {
font: inherit;
margin: 0;
}
optgroup {
font-weight: 700;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
[type="reset"],
[type="submit"],
button,
html [type="button"] {
-webkit-appearance: button;
}
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner,
button::-moz-focus-inner {
border-style: none;
padding: 0;
}
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring,
button:-moz-focusring {
outline: 1px dotted ButtonText;
}
fieldset {
border: 1px solid silver;
padding: 0.35em 0.625em 0.75em;
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
legend {
box-sizing: border-box;
color: inherit;
display: table;
max-width: 100%;
padding: 0;
white-space: normal;
}
textarea {
overflow: auto;
}
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
padding: 0;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-input-placeholder {
color: inherit;
opacity: 0.54;
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
* {
box-sizing: inherit;
}
*:before {
box-sizing: inherit;
}
*:after {
box-sizing: inherit;
}
h2 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 1.62671rem;
line-height: 1.1;
}
h3 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 1.38316rem;
line-height: 1.1;
}
h4 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 1rem;
line-height: 1.1;
}
h5 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 0.85028rem;
line-height: 1.1;
}
h6 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 0.78405rem;
line-height: 1.1;
}
hgroup {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
ul {
margin-left: 1.45rem;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
list-style-position: outside;
list-style-image: none;
}
ol {
margin-left: 1.45rem;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
list-style-position: outside;
list-style-image: none;
}
dl {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
dd {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
p {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
pre {
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 1.45rem;
font-size: 0.85rem;
line-height: 1.42;
background: hsla(0, 0%, 0%, 0.04);
border-radius: 3px;
overflow: auto;
word-wrap: normal;
padding: 1.45rem;
}
table {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
font-size: 1rem;
line-height: 1.45rem;
border-collapse: collapse;
width: 100%;
}
blockquote {
margin-left: 1.45rem;
margin-right: 1.45rem;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
form {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
noscript {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
iframe {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
address {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
b {
font-weight: bold;
}
strong {
font-weight: bold;
}
dt {
font-weight: bold;
}
th {
font-weight: bold;
}
li {
margin-bottom: calc(1.45rem / 2);
}
ol li {
padding-left: 0;
}
ul li {
padding-left: 0;
}
li > ol {
margin-left: 1.45rem;
margin-bottom: calc(1.45rem / 2);
margin-top: calc(1.45rem / 2);
}
li > ul {
margin-left: 1.45rem;
margin-bottom: calc(1.45rem / 2);
margin-top: calc(1.45rem / 2);
}
blockquote *:last-child {
margin-bottom: 0;
}
li *:last-child {
margin-bottom: 0;
}
p *:last-child {
margin-bottom: 0;
}
li > p {
margin-bottom: calc(1.45rem / 2);
}
code {
font-size: 0.85rem;
line-height: 1.45rem;
}
kbd {
font-size: 0.85rem;
line-height: 1.45rem;
}
samp {
font-size: 0.85rem;
line-height: 1.45rem;
}
abbr {
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
cursor: help;
}
acronym {
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
cursor: help;
}
thead {
text-align: left;
}
td,
th {
text-align: left;
border-bottom: 1px solid hsla(0, 0%, 0%, 0.12);
font-feature-settings: "tnum";
-moz-font-feature-settings: "tnum";
-ms-font-feature-settings: "tnum";
-webkit-font-feature-settings: "tnum";
padding-left: 0.96667rem;
padding-right: 0.96667rem;
padding-top: 0.725rem;
padding-bottom: calc(0.725rem - 1px);
}
th:first-child,
td:first-child {
padding-left: 0;
}
th:last-child,
td:last-child {
padding-right: 0;
}
tt,
code {
background-color: hsla(0, 0%, 0%, 0.04);
border-radius: 3px;
font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono",
"Liberation Mono", Menlo, Courier, monospace;
padding: 0;
padding-top: 0.2em;
padding-bottom: 0.2em;
}
pre code {
background: none;
line-height: 1.42;
}
code:before,
code:after,
tt:before,
tt:after {
letter-spacing: -0.2em;
content: " ";
}
pre code:before,
pre code:after,
pre tt:before,
pre tt:after {
content: "";
}
@media only screen and (max-width: 480px) {
html {
font-size: 100%;
}
}
/**
* Layout component that queries for data
* with Gatsby's useStaticQuery component
*
* See: https://www.gatsbyjs.com/docs/use-static-query/
*/
import * as React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import Header from "./header"
import "./layout.css"
const Layout = ({ children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
return (
<>
<Header siteTitle={data.site.siteMetadata?.title || `Title`} />
<div
style={{
margin: `0 auto`,
maxWidth: 960,
padding: `0 1.0875rem 1.45rem`,
}}
>
<main>{children}</main>
<footer
style={{
marginTop: `2rem`,
}}
>
© {new Date().getFullYear()}, Built with
{` `}
<a href="https://www.gatsbyjs.com">Gatsby</a>
</footer>
</div>
</>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
/**
* SEO component that queries for data with
* Gatsby's useStaticQuery React hook
*
* See: https://www.gatsbyjs.com/docs/use-static-query/
*/
import * as React from "react"
import PropTypes from "prop-types"
import { Helmet } from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"
function Seo({ description, lang, meta, title }) {
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
description
author
}
}
}
`
)
const metaDescription = description || site.siteMetadata.description
const defaultTitle = site.siteMetadata?.title
return (
<Helmet
htmlAttributes={{
lang,
}}
title={title}
titleTemplate={defaultTitle ? `%s | ${defaultTitle}` : null}
meta={[
{
name: `description`,
content: metaDescription,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: metaDescription,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary`,
},
{
name: `twitter:creator`,
content: site.siteMetadata?.author || ``,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: metaDescription,
},
].concat(meta)}
/>
)
}
Seo.defaultProps = {
lang: `en`,
meta: [],
description: ``,
}
Seo.propTypes = {
description: PropTypes.string,
lang: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
}
export default Seo
import * as React from "react"
import Layout from "../components/layout"
import Seo from "../components/seo"
const NotFoundPage = () => (
<Layout>
<Seo title="404: Not found" />
<h1>404: Not Found</h1>
<p>You just hit a route that doesn&#39;t exist... the sadness.</p>
</Layout>
)
export default NotFoundPage
import React from "react"
import Layout from "../components/layout"
import Seo from "../components/seo"
export default function About() {
return (
<Layout>
<Seo title="About this site" />
<div>
<h1>About this site</h1>
<h2>Built with Gatsby</h2>
<p>Such wow. Very React.</p>
</div>
</Layout>
)
}
import * as React from "react"
import { Link } from "gatsby"
import { StaticImage } from "gatsby-plugin-image"
import Layout from "../components/layout"
import Seo from "../components/seo"
const IndexPage = () => (
<Layout>
<Seo title="PLN's Home" />
<h1>Welcome!</h1>
<h2>I'm PLN, and I love to <b>transform</b>
</h2>
<p>This is gonna be great.</p>
<StaticImage
src="../images/WIP_GaLactic.png"
width={2048}
quality={95}
formats={["AUTO", "WEBP", "AVIF"]}
alt="A Gatsby astronaut"
style={{ marginBottom: `1.45rem` }}
/>
<p>
<Link to="/page-2/">Go to page 2</Link> <br />
<Link to="/using-typescript/">Go to "Using TypeScript"</Link>
</p>
</Layout>
)
export default IndexPage
import * as React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"
import Seo from "../components/seo"
const SecondPage = () => (
<Layout>
<Seo title="Page two" />
<h1>Hi from the second page</h1>
<p>Welcome to page 2</p>
<Link to="/">Go back to the homepage</Link>
</Layout>
)
export default SecondPage
// If you don't want to use TypeScript you can delete this file!
import * as React from "react"
import { PageProps, Link, graphql } from "gatsby"
import Layout from "../components/layout"
import Seo from "../components/seo"
type DataProps = {
site: {
buildTime: string
}
}
const UsingTypescript: React.FC<PageProps<DataProps>> = ({ data, path }) => (
<Layout>
<Seo title="Using TypeScript" />
<h1>Gatsby supports TypeScript by default!</h1>
<p>
This means that you can create and write <em>.ts/.tsx</em> files for your
pages, components etc. Please note that the <em>gatsby-*.js</em> files
(like gatsby-node.js) currently don't support TypeScript yet.
</p>
<p>
For type checking you'll want to install <em>typescript</em> via npm and
run <em>tsc --init</em> to create a <em>.tsconfig</em> file.
</p>
<p>
You're currently on the page "{path}" which was built on{" "}
{data.site.buildTime}.
</p>
<p>
To learn more, head over to our{" "}
<a href="https://www.gatsbyjs.com/docs/typescript/">
documentation about TypeScript
</a>
.
</p>
<Link to="/">Go back to the homepage</Link>
</Layout>
)
export default UsingTypescript
export const query = graphql`
{
site {
buildTime(formatString: "YYYY-MM-DD hh:mm a z")
}
}
`
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment