diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 3ef4919..b5a5b02 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,8 +12,6 @@ jobs: uses: actions/checkout@v2.3.1 with: persist-credentials: false - - run: corepack enable - - name: Install uses: docker://ghcr.io/morten-olsen/node-latex:main with: diff --git a/articles/content/2022-03-15-my-home-runs-redux/article.yml b/articles/content/2022-03-15-my-home-runs-redux/article.yml index 310b6e3..0488991 100644 --- a/articles/content/2022-03-15-my-home-runs-redux/article.yml +++ b/articles/content/2022-03-15-my-home-runs-redux/article.yml @@ -1,7 +1,8 @@ title: My home runs Redux cover: cover.png -published: 2022-03-15 meta: slug: my-home-runs-redux + published: 2022-03-15 + color: '#e80ccf' content: - main.md diff --git a/articles/content/2022-03-16-hiring/article.yml b/articles/content/2022-03-16-hiring/article.yml index c9fbb8e..8cc0555 100644 --- a/articles/content/2022-03-16-hiring/article.yml +++ b/articles/content/2022-03-16-hiring/article.yml @@ -1,7 +1,8 @@ title: How to hire engineers, by an engineer cover: cover.png -published: 2022-03-16 meta: - slug: hiring-by-an-engineer + slug: hiring + published: 2022-03-16 + color: "#8bae8c" content: - main.md diff --git a/articles/content/2022-04-15-coding-challange/article.yml b/articles/content/2022-04-15-coding-challange/article.yml index 7ccf0ee..e37bacc 100644 --- a/articles/content/2022-04-15-coding-challange/article.yml +++ b/articles/content/2022-04-15-coding-challange/article.yml @@ -1,7 +1,8 @@ title: A defence for the coding challange -published: 2022-04-15 cover: cover.png meta: + published: 2022-04-15 slug: a-defence-for-the-code-challange + color: "#3d91ef" content: - file: main.md diff --git a/articles/content/2022-05-06-bob-the-algorithm/article.yml b/articles/content/2022-05-06-bob-the-algorithm/article.yml index b553d2b..d3c3127 100644 --- a/articles/content/2022-05-06-bob-the-algorithm/article.yml +++ b/articles/content/2022-05-06-bob-the-algorithm/article.yml @@ -1,7 +1,8 @@ title: My day is being planned by an algorithm cover: ./Cover.png -published: 2022-05-06 meta: slug: bob-the-algorithm + published: 2022-05-06 + color: '#e7d9ac' content: - main.md diff --git a/articles/content/2022-12-05-git-strategy/article.yml b/articles/content/2022-12-05-git-strategy/article.yml index 0db0b7e..273b36d 100644 --- a/articles/content/2022-12-05-git-strategy/article.yml +++ b/articles/content/2022-12-05-git-strategy/article.yml @@ -1,7 +1,9 @@ title: A meta talk about Git strategies cover: cover.png meta: - slug: git-strategy + slug: a-meta-talk-about-git-strategies + published: 2022-12-05 + color: '#01eeed' content: - content: - file: intro-story.md diff --git a/package.json b/package.json index 22dbd48..2bd168b 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "scripts": { "cli": "yarn workspace @morten-olsen/goodwrites-cli run cli", "dev": "yarn workspace @morten-olsen/personal-webpage next dev", - "build": "yarn workspace @morten-olsen/personal-webpage next build && yarn workspace @morten-olsen/personal-webpage next export", + "build": "tsc --build && yarn workspace @morten-olsen/personal-webpage next build && yarn workspace @morten-olsen/personal-webpage next export", "postinstall": "husky install" }, "private": true, diff --git a/packages/goodwrites-latex/src/parser/utils.ts b/packages/goodwrites-latex/src/parser/utils.ts index 96e32da..14b4280 100644 --- a/packages/goodwrites-latex/src/parser/utils.ts +++ b/packages/goodwrites-latex/src/parser/utils.ts @@ -68,7 +68,6 @@ const renderer = (outerDepth: number) => ({ return `\\item{${input}}`; }, link: (href: string, text: string) => { - console.log('LINK TEXT', text, sanitize(href)); if (!text || text === href) { return `\\url{${sanitize(href)}}`; } diff --git a/webpage/package.json b/webpage/package.json index 561218f..a90dde2 100644 --- a/webpage/package.json +++ b/webpage/package.json @@ -2,8 +2,11 @@ "name": "@morten-olsen/personal-webpage", "private": true, "dependencies": { + "@fontsource/black-ops-one": "^4.5.9", "@fontsource/merriweather": "^4.5.14", "@fontsource/pacifico": "^4.5.9", + "@fontsource/space-grotesk": "^4.5.10", + "@fontsource/vt323": "^4.5.10", "@morten-olsen/markdown-loader": "workspace:^", "@morten-olsen/personal-webpage-articles": "workspace:^", "@morten-olsen/personal-webpage-profile": "workspace:^", diff --git a/webpage/src/components/articles/grid/index.tsx b/webpage/src/components/articles/grid/index.tsx new file mode 100644 index 0000000..8b69b3a --- /dev/null +++ b/webpage/src/components/articles/grid/index.tsx @@ -0,0 +1,76 @@ +import React, { useMemo } from 'react'; +import styled from 'styled-components'; +import { getArticles } from '@morten-olsen/personal-webpage-articles/dist/index'; +import ArticlePreview from '../preview'; +import { JumboArticlePreview } from '../preview/jumbo'; +import { MiniArticlePreview } from '../preview/mini'; + +type Props = { + articles: ReturnType; +}; + +const Wrapper = styled.div` + width: 100%; +`; + +const FeaturedArticle = styled.div` + display: flex; + flex-wrap: wrap; + margin: 0 auto; + align-items: center; + justify-content: center; + width: 100%; +`; + +const FeaturedArticles = styled.div` + display: flex; + flex-direction: row; + margin: 0 auto; + width: 100%; + flex-wrap: wrap; +`; + +const RemainingArticles = styled.div` + display: flex; + flex-direction: row; + flex-wrap: wrap; + margin: 0 auto; + width: 100%; +`; + +const ArticleGrid: React.FC = ({ articles }) => { + const sorted = useMemo( + () => + articles.sort( + (a, b) => + new Date(b.meta.published).getTime() - + new Date(a.meta.published).getTime() + ), + [articles] + ); + const featured1 = useMemo(() => sorted.slice(0, 1)[0], [sorted]); + + const featured2 = useMemo(() => sorted.slice(1, 4), [sorted]); + + const remaining = useMemo(() => sorted.slice(4, 12), [sorted]); + + return ( + + + + + + {featured2.map((article) => ( + + ))} + + + {remaining.map((article) => ( + + ))} + + + ); +}; + +export { ArticleGrid }; diff --git a/webpage/src/components/articles/preview/index.tsx b/webpage/src/components/articles/preview/index.tsx index 2f49514..37d2ab1 100644 --- a/webpage/src/components/articles/preview/index.tsx +++ b/webpage/src/components/articles/preview/index.tsx @@ -1,30 +1,46 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import styled from 'styled-components'; import Link from 'next/link'; import { Title1 } from 'typography'; import { getArticles } from '@morten-olsen/personal-webpage-articles/dist/index'; +import { createTheme } from 'theme/create'; +import { ThemeProvider } from 'theme/provider'; type Props = { article: ReturnType[number]; }; const Wrapper = styled.div` - height: 300px; - width: 300px; + height: 500px; + border-right: 2px solid rgba(0, 0, 0, 0.1); + flex: 1; + min-width: 200px; position: relative; - margin: 10px; + margin: 15px; + cursor: pointer; + display: flex; + flex-direction: column; + + @media only screen and (max-width: 700px) { + max-height: 300px; + } `; const Title = styled(Title1)` background: ${({ theme }) => theme.colors.primary}; - padding: 5px 0; line-height: 40px; + font-family: 'Black Ops One', sans-serif; + font-size: 25px; + padding: 0 5px; + margin: 5px 0; `; const MetaWrapper = styled.div` - position: absolute; - top: 0; + top: 10px; left: 10px; + right: 10px; + display: flex; + flex-wrap: wrap; `; const AsideWrapper = styled.aside<{ @@ -34,7 +50,7 @@ const AsideWrapper = styled.aside<{ background-size: cover; background-position: center; ${({ image }) => (image ? `background-image: url(${image});` : '')} - position: absolute; + flex: 1; top: 0; bottom: 0; right: 0; @@ -43,15 +59,26 @@ const AsideWrapper = styled.aside<{ `; const ArticlePreview: React.FC = ({ article }) => { + const theme = useMemo( + () => + createTheme({ + baseColor: article.meta.color, + }), + [article.meta.color] + ); return ( - - - - - {article.title} - - - + + + + + + {article.title.split(' ').map((word, index) => ( + {word} + ))} + + + + ); }; diff --git a/webpage/src/components/articles/preview/jumbo.tsx b/webpage/src/components/articles/preview/jumbo.tsx new file mode 100644 index 0000000..8b133bd --- /dev/null +++ b/webpage/src/components/articles/preview/jumbo.tsx @@ -0,0 +1,82 @@ +import React from 'react'; +import styled from 'styled-components'; +import Link from 'next/link'; +import { Title1, Body1 } from 'typography'; +import { getArticles } from '@morten-olsen/personal-webpage-articles/dist/index'; + +type Props = { + article: ReturnType[number]; +}; + +const Wrapper = styled.a` + height: 300px; + flex: 1; + position: relative; + margin: 15px; + cursor: pointer; + display: flex; + background: ${({ theme }) => theme.colors.background}; + + @media only screen and (max-width: 700px) { + flex-direction: column; + height: 500px; + } +`; + +const Title = styled(Title1)` + line-height: 40px; + font-family: 'Black Ops One', sans-serif; + font-size: 25px; + padding: 0 5px; + margin: 5px 0; +`; + +const Summery = styled(Body1)` + max-width: 300px; + padding: 0 5px; + margin: 5px 0; + overflow: hidden; + letter-spacing: 0.5px; + line-height: 2.1rem; + + @media only screen and (max-width: 700px) { + max-height: 100px; + } +`; + +const MetaWrapper = styled.div` + display: flex; + flex-direction: column; + padding: 40px; +`; + +const AsideWrapper = styled.aside<{ + image?: string; +}>` + background: ${({ theme }) => theme.colors.primary}; + background-size: cover; + background-position: center; + ${({ image }) => (image ? `background-image: url(${image});` : '')} + flex: 1; + top: 0; + bottom: 0; + right: 0; + left: 0; +} +`; + +const JumboArticlePreview: React.FC = ({ article }) => { + return ( + + + + + {article.title} + {article.content} + + + + ); +}; + +export { JumboArticlePreview }; diff --git a/webpage/src/components/articles/preview/mini.tsx b/webpage/src/components/articles/preview/mini.tsx new file mode 100644 index 0000000..04d6fdf --- /dev/null +++ b/webpage/src/components/articles/preview/mini.tsx @@ -0,0 +1,83 @@ +import React, { useMemo } from 'react'; +import styled from 'styled-components'; +import Link from 'next/link'; +import { Title1 } from 'typography'; +import { getArticles } from '@morten-olsen/personal-webpage-articles/dist/index'; +import { createTheme } from 'theme/create'; +import { ThemeProvider } from 'theme/provider'; + +type Props = { + article: ReturnType[number]; +}; + +const Wrapper = styled.a` + position: relative; + margin: 15px; + cursor: pointer; + display: flex; + width: 220px; + height: 200px; + + @media only screen and (max-width: 700px) { + width: 100%; + } +`; + +const Title = styled(Title1)` + line-height: 20px; + font-size: 20px; + padding: 5px 5px; + font-family: 'Black Ops One', sans-serif; + margin: 5px 0; + background: ${({ theme }) => theme.colors.background}; +`; + +const MetaWrapper = styled.div` + display: flex; + flex-direction: row; + flex-wrap: wrap; + padding: 10px; + max-width: 220px; + position: absolute; +`; + +const AsideWrapper = styled.aside<{ + image?: string; +}>` + background: ${({ theme }) => theme.colors.primary}; + background-size: cover; + background-position: center; + ${({ image }) => (image ? `background-image: url(${image});` : '')} + position: absolute; + top: 0; + bottom: 0; + right: 0; + left: 0; +} +`; + +const MiniArticlePreview: React.FC = ({ article }) => { + const theme = useMemo( + () => + createTheme({ + baseColor: article.meta.color, + }), + [article.meta.color] + ); + return ( + + + + + + {article.title.split(' ').map((word, index) => ( + {word} + ))} + + + + + ); +}; + +export { MiniArticlePreview }; diff --git a/webpage/src/components/sheet/index.tsx b/webpage/src/components/sheet/index.tsx index 6432928..26c127b 100644 --- a/webpage/src/components/sheet/index.tsx +++ b/webpage/src/components/sheet/index.tsx @@ -6,7 +6,7 @@ import { ThemeProvider } from 'theme/provider'; const Wrapper = styled.div` background: ${({ theme }) => theme.colors.background}; color: ${({ theme }) => theme.colors.foreground}; - min-height: 90%; + min-height: 100%; position: relative; display: flex; align-items: center; @@ -14,27 +14,49 @@ const Wrapper = styled.div` flex-direction: column; `; -const BackgroundWrapper = styled.div` +const BackgroundWrapper = styled.div<{ + image: string; +}>` position: absolute; + left: 0; top: 0; bottom: 0; - left: 0; right: 0; + background-size: cover; + background-position: center; + opacity: 0.2; + ${({ image }) => (image ? `background-image: url(${image});` : '')} +`; + +const Content = styled.div` + z-index: 1; + display: flex; + max-width: 1000px; + width: 100%; + align-items: center; + justify-content: center; + flex-direction: column; `; type Props = { - backgroundColor: string; children: ReactNode; - background?: ReactNode; + background?: string; + color?: string; }; -const Sheet: React.FC = ({ background, children }) => { - const theme = useMemo(() => createTheme({}), []); +const Sheet: React.FC = ({ color, background, children }) => { + const theme = useMemo( + () => + createTheme({ + baseColor: color, + }), + [color] + ); return ( - {background && {background}} - {children} + + {children} ); diff --git a/webpage/src/pages/_app.tsx b/webpage/src/pages/_app.tsx index cabae31..3f36f95 100644 --- a/webpage/src/pages/_app.tsx +++ b/webpage/src/pages/_app.tsx @@ -4,6 +4,8 @@ import type { AppProps } from 'next/app'; import Head from 'next/head'; import '@fontsource/merriweather'; import '@fontsource/pacifico'; +import '@fontsource/space-grotesk/700.css'; +import '@fontsource/black-ops-one'; import { ThemeProvider } from '../theme/provider'; import { createTheme } from '../theme/create'; import chroma from 'chroma-js'; @@ -34,6 +36,7 @@ const GlobalStyle = createGlobalStyle` a { text-decoration: none; + font-weight: bold; } `; diff --git a/webpage/src/pages/articles/[slug].tsx b/webpage/src/pages/articles/[slug].tsx index 04113f0..915014f 100644 --- a/webpage/src/pages/articles/[slug].tsx +++ b/webpage/src/pages/articles/[slug].tsx @@ -1,15 +1,19 @@ import { getArticles } from '@morten-olsen/personal-webpage-articles'; import { GetStaticPaths, GetStaticProps } from 'next'; import styled from 'styled-components'; -import React from 'react'; +import React, { useMemo } from 'react'; import { ReactMarkdown } from 'react-markdown/lib/react-markdown'; import { Jumbo, Overline } from 'typography'; +import { ThemeProvider } from 'theme/provider'; +import { createTheme } from 'theme/create'; type Props = { article: ReturnType[number]; }; -const Wrapper = styled.div``; +const Wrapper = styled.div` + background: ${({ theme }) => theme.colors.background}; +`; const ArticleWrapper = styled.article` margin-right: 40%; @@ -40,7 +44,6 @@ const ArticleContent = styled.div` float: left; padding: 1rem; margin: 0px 2rem; - font-weight: 100; margin-left: 0rem; } @@ -73,6 +76,7 @@ const ArticleContent = styled.div` margin: 5px 0; background: ${({ theme }) => theme.colors.primary}; color: ${({ theme }) => theme.colors.foreground}; + font-family: 'Black Ops One', sans-serif; @media only screen and (max-width: 700px) { background: transparent; @@ -92,7 +96,7 @@ const AsideWrapper = styled.aside<{ background: ${({ theme }) => theme.colors.primary}; background-size: cover; background-position: center; - opacity: 0.5; + opacity: 0.7; ${({ image }) => (image ? `background-image: url(${image});` : '')} @media only screen and (max-width: 700px) { @@ -105,16 +109,23 @@ const AsideWrapper = styled.aside<{ `; const Title = styled(Jumbo)` - font-size: 60px; - line-height: 80px; + font-size: 4rem; + line-height: 4.1rem; display: inline-block; background: ${({ theme }) => theme.colors.primary}; color: ${({ theme }) => theme.colors.foreground}; padding: 0 15px; text-transform: uppercase; margin: 5px; + font-family: 'Black Ops One', sans-serif; + + @media only screen and (max-width: 900px) { + font-size: 2.5rem; + line-height: 3.1rem; + } @media only screen and (max-width: 700px) { + padding: 5px; font-size: 2rem; line-height: 2.1rem; } @@ -125,28 +136,37 @@ const Meta = styled(Overline)` `; const Article: React.FC = ({ article }) => { + const theme = useMemo( + () => + createTheme({ + baseColor: article.meta.color, + }), + [article.meta.color] + ); return ( - - - - {article.title.split(' ').map((word, index) => ( - {word} - ))} -
- - By Morten Olsen - 5 min read{' '} - {article.pdf && ( - - download as PDF - - )} - -
- - {article.content} -
-
-
+ + + + + {article.title.split(' ').map((word, index) => ( + {word} + ))} +
+ + By Morten Olsen - {article.stats.text}{' '} + {article.pdf && ( + + download as PDF + + )} + +
+ + {article.content} +
+
+
+
); }; diff --git a/webpage/src/pages/cover.png b/webpage/src/pages/cover.png new file mode 100644 index 0000000..77f2208 Binary files /dev/null and b/webpage/src/pages/cover.png differ diff --git a/webpage/src/pages/index.tsx b/webpage/src/pages/index.tsx index d971e8c..d80b61a 100644 --- a/webpage/src/pages/index.tsx +++ b/webpage/src/pages/index.tsx @@ -5,7 +5,8 @@ import { getArticles } from '@morten-olsen/personal-webpage-articles/dist/index' import { GetStaticProps } from 'next'; import { getPositions, Position } from '@morten-olsen/personal-webpage-profile'; import { Sheet } from '../components/sheet'; -import ArticlePreview from 'components/articles/preview'; +import { ArticleGrid } from 'components/articles/grid'; +const cover = require('./cover.png'); type Props = { articles: ReturnType; @@ -25,29 +26,48 @@ const Title = styled(Jumbo)` color: ${({ theme }) => theme.colors.foreground}; padding: 0 15px; text-transform: uppercase; - margin: 5px; + margin: 10px; + font-family: 'Black Ops One', sans-serif; @media only screen and (max-width: 700px) { + margin: 5px; font-size: 2rem; line-height: 2.1rem; } `; -const ArticleList = styled.div` +const Arrow = styled.div` + position: absolute; + bottom: 20px; display: flex; - flex-direction: row; - flex-wrap: wrap; - margin: 0 auto; align-items: center; justify-content: center; + + :after { + display: flex; + align-items: center; + justify-content: center; + background: ${({ theme }) => theme.colors.primary}; + border-radius: 50%; + width: 80px; + height: 80px; + content: '↓'; + font-size: 50px; + + @media only screen and (max-width: 700px) { + width: 40px; + height: 40px; + } + } `; -const Index: FC = ({ articles, positions }) => { +const Index: FC = ({ articles }) => { return ( <> - + + - {"Hi, I'm Morten Olsen".split(' ').map((char, index) => ( + {"Hi, I'm Morten".split(' ').map((char, index) => ( {char} ))} @@ -57,18 +77,13 @@ const Index: FC = ({ articles, positions }) => { ))} - -

Articles

- - {articles.map((article) => ( - + + + {'Table of Content'.split(' ').map((char, index) => ( + {char} ))} - -
- - {positions.map((position) => ( -
{position.attributes.title}
- ))} + +
); @@ -77,7 +92,6 @@ const Index: FC = ({ articles, positions }) => { export const getStaticProps: GetStaticProps = async () => { const articles = getArticles(); const positions = getPositions(); - console.log(articles); return { props: { articles, diff --git a/webpage/src/theme/create.ts b/webpage/src/theme/create.ts index 854d8a5..b022ed0 100644 --- a/webpage/src/theme/create.ts +++ b/webpage/src/theme/create.ts @@ -17,7 +17,7 @@ const createTheme = (options: CreateOptions = {}) => { const text = isBright(baseColor) ? BLACK : WHITE; const bg = isBright(baseColor) ? baseColor.luminance(0.9) - : baseColor.luminance(0.005); + : baseColor.luminance(0.01); const theme: Theme = { typography: { Jumbo: { diff --git a/yarn.lock b/yarn.lock index d67bb83..2275698 100644 --- a/yarn.lock +++ b/yarn.lock @@ -693,6 +693,13 @@ __metadata: languageName: node linkType: hard +"@fontsource/black-ops-one@npm:^4.5.9": + version: 4.5.9 + resolution: "@fontsource/black-ops-one@npm:4.5.9" + checksum: 514735092abc24f1548d3acdb84f224f15977255c4fc69f3217a280d9660168e5389ce47eab26be76989c9234f824a3e7b3ef7e5ea78880b2fff08d1e3879c57 + languageName: node + linkType: hard + "@fontsource/merriweather@npm:^4.5.14": version: 4.5.14 resolution: "@fontsource/merriweather@npm:4.5.14" @@ -707,6 +714,20 @@ __metadata: languageName: node linkType: hard +"@fontsource/space-grotesk@npm:^4.5.10": + version: 4.5.10 + resolution: "@fontsource/space-grotesk@npm:4.5.10" + checksum: 71c05e9ce7c88b9f63bf7ed1e0460fccac1339ef679218b4d5404298b27a829e6dc7fe1f4de99105dddbff57b5902dfce901b252d466795f51051339fd931ad8 + languageName: node + linkType: hard + +"@fontsource/vt323@npm:^4.5.10": + version: 4.5.10 + resolution: "@fontsource/vt323@npm:4.5.10" + checksum: 99f6a1d1add1d5002b3332ccc0b3d8185c635bce8129e16d084c3a4b421a13d5f96863b293e089c77291adfb032f943123b27b1080b7cc89178e52d4d2f64e91 + languageName: node + linkType: hard + "@gar/promisify@npm:^1.1.3": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" @@ -1205,8 +1226,11 @@ __metadata: version: 0.0.0-use.local resolution: "@morten-olsen/personal-webpage@workspace:webpage" dependencies: + "@fontsource/black-ops-one": ^4.5.9 "@fontsource/merriweather": ^4.5.14 "@fontsource/pacifico": ^4.5.9 + "@fontsource/space-grotesk": ^4.5.10 + "@fontsource/vt323": ^4.5.10 "@morten-olsen/goodwrites-webpack-loader": "workspace:^" "@morten-olsen/markdown-loader": "workspace:^" "@morten-olsen/personal-webpage-articles": "workspace:^"