feat: redesign

This commit is contained in:
Andreas Thomas 2023-02-27 20:19:40 +01:00
parent 9398052466
commit e57c10249b
No known key found for this signature in database
72 changed files with 5488 additions and 368 deletions

View File

@ -0,0 +1,96 @@
// contentlayer.config.js
import { defineDocumentType, makeSource } from "contentlayer/source-files";
import remarkGfm from "remark-gfm";
import rehypePrettyCode from "rehype-pretty-code";
import rehypeSlug from "rehype-slug";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
var computedFields = {
path: {
type: "string",
resolve: (doc) => `/${doc._raw.flattenedPath}`,
},
slug: {
type: "string",
resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/"),
},
};
var Project = defineDocumentType(() => ({
name: "Project",
filePathPattern: "./projects/**/*.mdx",
contentType: "mdx",
fields: {
title: {
type: "string",
required: true,
},
description: {
type: "string",
},
date: {
type: "date",
required: true,
},
url: {
type: "string",
required: true,
},
repository: {
type: "string",
required: true,
},
},
computedFields,
}));
var Page = defineDocumentType(() => ({
name: "Page",
filePathPattern: "pages/**/*.mdx",
contentType: "mdx",
fields: {
title: {
type: "string",
required: true,
},
description: {
type: "string",
},
},
computedFields,
}));
var contentlayer_config_default = makeSource({
contentDirPath: "./content",
documentTypes: [Page, Project, Author, Tech],
mdx: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
rehypeSlug,
[
rehypePrettyCode,
{
theme: "github-dark",
onVisitLine(node) {
if (node.children.length === 0) {
node.children = [{ type: "text", value: " " }];
}
},
onVisitHighlightedLine(node) {
node.properties.className.push("line--highlighted");
},
onVisitHighlightedWord(node) {
node.properties.className = ["word--highlighted"];
},
},
],
[
rehypeAutolinkHeadings,
{
properties: {
className: ["subheading-anchor"],
ariaLabel: "Link to section",
},
},
],
],
},
});
export { Page, Project, contentlayer_config_default as default };
//# sourceMappingURL=compiled-contentlayer-config-45X2WG6B.mjs.map

View File

@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../../contentlayer.config.js"],
"sourcesContent": ["import { defineDocumentType, makeSource } from \"contentlayer/source-files\";\nimport remarkGfm from \"remark-gfm\";\nimport rehypePrettyCode from \"rehype-pretty-code\";\nimport rehypeSlug from \"rehype-slug\";\nimport rehypeAutolinkHeadings from \"rehype-autolink-headings\";\n\n/** @type {import('contentlayer/source-files').ComputedFields} */\nconst computedFields = {\n\tpath: {\n\t\ttype: \"string\",\n\t\tresolve: (doc) => `/${doc._raw.flattenedPath}`,\n\t},\n\tslug: {\n\t\ttype: \"string\",\n\t\tresolve: (doc) => doc._raw.flattenedPath.split(\"/\").slice(1).join(\"/\"),\n\t},\n};\n\nexport const Project = defineDocumentType(() => ({\n\tname: \"Project\",\n\tfilePathPattern: \"./projects/**/*.mdx\",\n\tcontentType: \"mdx\",\n\n\tfields: {\n\t\ttitle: {\n\t\t\ttype: \"string\",\n\t\t\trequired: true,\n\t\t},\n\t\tdescription: {\n\t\t\ttype: \"string\",\n\t\t},\n\t\tdate: {\n\t\t\ttype: \"date\",\n\t\t\trequired: true,\n\t\t},\n\t\turl: {\n\t\t\ttype: \"string\",\n\t\t\trequired: true,\n\t\t},\n\t\trepository: {\n\t\t\ttype: \"string\",\n\t\t\trequired: true,\n\t\t},\n\t},\n\tcomputedFields,\n}));\n\nexport const Page = defineDocumentType(() => ({\n\tname: \"Page\",\n\tfilePathPattern: \"pages/**/*.mdx\",\n\tcontentType: \"mdx\",\n\tfields: {\n\t\ttitle: {\n\t\t\ttype: \"string\",\n\t\t\trequired: true,\n\t\t},\n\t\tdescription: {\n\t\t\ttype: \"string\",\n\t\t},\n\t},\n\tcomputedFields,\n}));\n\nexport default makeSource({\n\tcontentDirPath: \"./content\",\n\tdocumentTypes: [Page, Project, Author, Tech],\n\tmdx: {\n\t\tremarkPlugins: [remarkGfm],\n\t\trehypePlugins: [\n\t\t\trehypeSlug,\n\t\t\t[\n\t\t\t\trehypePrettyCode,\n\t\t\t\t{\n\t\t\t\t\ttheme: \"github-dark\",\n\t\t\t\t\tonVisitLine(node) {\n\t\t\t\t\t\t// Prevent lines from collapsing in `display: grid` mode, and allow empty\n\t\t\t\t\t\t// lines to be copy/pasted\n\t\t\t\t\t\tif (node.children.length === 0) {\n\t\t\t\t\t\t\tnode.children = [{ type: \"text\", value: \" \" }];\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tonVisitHighlightedLine(node) {\n\t\t\t\t\t\tnode.properties.className.push(\"line--highlighted\");\n\t\t\t\t\t},\n\t\t\t\t\tonVisitHighlightedWord(node) {\n\t\t\t\t\t\tnode.properties.className = [\"word--highlighted\"];\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\t[\n\t\t\t\trehypeAutolinkHeadings,\n\t\t\t\t{\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tclassName: [\"subheading-anchor\"],\n\t\t\t\t\t\tariaLabel: \"Link to section\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t],\n\t},\n});\n"],
"mappings": ";AAAA,SAAS,oBAAoB,kBAAkB;AAC/C,OAAO,eAAe;AACtB,OAAO,sBAAsB;AAC7B,OAAO,gBAAgB;AACvB,OAAO,4BAA4B;AAGnC,IAAM,iBAAiB;AAAA,EACtB,MAAM;AAAA,IACL,MAAM;AAAA,IACN,SAAS,CAAC,QAAQ,IAAI,IAAI,KAAK;AAAA,EAChC;AAAA,EACA,MAAM;AAAA,IACL,MAAM;AAAA,IACN,SAAS,CAAC,QAAQ,IAAI,KAAK,cAAc,MAAM,GAAG,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG;AAAA,EACtE;AACD;AAEO,IAAM,UAAU,mBAAmB,OAAO;AAAA,EAChD,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,aAAa;AAAA,EAEb,QAAQ;AAAA,IACP,OAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IACX;AAAA,IACA,aAAa;AAAA,MACZ,MAAM;AAAA,IACP;AAAA,IACA,MAAM;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,IACX;AAAA,IACA,KAAK;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,IACX;AAAA,IACA,YAAY;AAAA,MACX,MAAM;AAAA,MACN,UAAU;AAAA,IACX;AAAA,EACD;AAAA,EACA;AACD,EAAE;AAEK,IAAM,OAAO,mBAAmB,OAAO;AAAA,EAC7C,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,QAAQ;AAAA,IACP,OAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IACX;AAAA,IACA,aAAa;AAAA,MACZ,MAAM;AAAA,IACP;AAAA,EACD;AAAA,EACA;AACD,EAAE;AAEF,IAAO,8BAAQ,WAAW;AAAA,EACzB,gBAAgB;AAAA,EAChB,eAAe,CAAC,MAAM,SAAS,QAAQ,IAAI;AAAA,EAC3C,KAAK;AAAA,IACJ,eAAe,CAAC,SAAS;AAAA,IACzB,eAAe;AAAA,MACd;AAAA,MACA;AAAA,QACC;AAAA,QACA;AAAA,UACC,OAAO;AAAA,UACP,YAAY,MAAM;AAGjB,gBAAI,KAAK,SAAS,WAAW,GAAG;AAC/B,mBAAK,WAAW,CAAC,EAAE,MAAM,QAAQ,OAAO,IAAI,CAAC;AAAA,YAC9C;AAAA,UACD;AAAA,UACA,uBAAuB,MAAM;AAC5B,iBAAK,WAAW,UAAU,KAAK,mBAAmB;AAAA,UACnD;AAAA,UACA,uBAAuB,MAAM;AAC5B,iBAAK,WAAW,YAAY,CAAC,mBAAmB;AAAA,UACjD;AAAA,QACD;AAAA,MACD;AAAA,MACA;AAAA,QACC;AAAA,QACA;AAAA,UACC,YAAY;AAAA,YACX,WAAW,CAAC,mBAAmB;AAAA,YAC/B,WAAW;AAAA,UACZ;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD,CAAC;",
"names": []
}

View File

@ -0,0 +1,98 @@
// contentlayer.config.js
import { defineDocumentType, makeSource } from "contentlayer/source-files";
import remarkGfm from "remark-gfm";
import rehypePrettyCode from "rehype-pretty-code";
import rehypeSlug from "rehype-slug";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
var computedFields = {
path: {
type: "string",
resolve: (doc) => `/${doc._raw.flattenedPath}`
},
slug: {
type: "string",
resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/")
}
};
var Project = defineDocumentType(() => ({
name: "Project",
filePathPattern: "./projects/**/*.mdx",
contentType: "mdx",
fields: {
title: {
type: "string",
required: true
},
description: {
type: "string",
required: true
},
date: {
type: "date"
},
url: {
type: "string"
},
repository: {
type: "string"
}
},
computedFields
}));
var Page = defineDocumentType(() => ({
name: "Page",
filePathPattern: "pages/**/*.mdx",
contentType: "mdx",
fields: {
title: {
type: "string",
required: true
},
description: {
type: "string"
}
},
computedFields
}));
var contentlayer_config_default = makeSource({
contentDirPath: "./content",
documentTypes: [Page, Project],
mdx: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
rehypeSlug,
[
rehypePrettyCode,
{
theme: "github-dark",
onVisitLine(node) {
if (node.children.length === 0) {
node.children = [{ type: "text", value: " " }];
}
},
onVisitHighlightedLine(node) {
node.properties.className.push("line--highlighted");
},
onVisitHighlightedWord(node) {
node.properties.className = ["word--highlighted"];
}
}
],
[
rehypeAutolinkHeadings,
{
properties: {
className: ["subheading-anchor"],
ariaLabel: "Link to section"
}
}
]
]
}
});
export {
Page,
Project,
contentlayer_config_default as default
};
//# sourceMappingURL=compiled-contentlayer-config-KFUTZ636.mjs.map

View File

@ -0,0 +1,7 @@
{
"version": 3,
"sources": ["../../../contentlayer.config.js"],
"sourcesContent": ["import { defineDocumentType, makeSource } from \"contentlayer/source-files\";\nimport remarkGfm from \"remark-gfm\";\nimport rehypePrettyCode from \"rehype-pretty-code\";\nimport rehypeSlug from \"rehype-slug\";\nimport rehypeAutolinkHeadings from \"rehype-autolink-headings\";\n\n/** @type {import('contentlayer/source-files').ComputedFields} */\nconst computedFields = {\n\tpath: {\n\t\ttype: \"string\",\n\t\tresolve: (doc) => `/${doc._raw.flattenedPath}`,\n\t},\n\tslug: {\n\t\ttype: \"string\",\n\t\tresolve: (doc) => doc._raw.flattenedPath.split(\"/\").slice(1).join(\"/\"),\n\t},\n};\n\nexport const Project = defineDocumentType(() => ({\n\tname: \"Project\",\n\tfilePathPattern: \"./projects/**/*.mdx\",\n\tcontentType: \"mdx\",\n\n\tfields: {\n\t\ttitle: {\n\t\t\ttype: \"string\",\n\t\t\trequired: true,\n\t\t},\n\t\tdescription: {\n\t\t\ttype: \"string\",\n\t\t\trequired: true,\n\t\t},\n\t\tdate: {\n\t\t\ttype: \"date\",\n\t\t},\n\t\turl: {\n\t\t\ttype: \"string\",\n\t\t},\n\t\trepository: {\n\t\t\ttype: \"string\",\n\t\t},\n\t},\n\tcomputedFields,\n}));\n\nexport const Page = defineDocumentType(() => ({\n\tname: \"Page\",\n\tfilePathPattern: \"pages/**/*.mdx\",\n\tcontentType: \"mdx\",\n\tfields: {\n\t\ttitle: {\n\t\t\ttype: \"string\",\n\t\t\trequired: true,\n\t\t},\n\t\tdescription: {\n\t\t\ttype: \"string\",\n\t\t},\n\t},\n\tcomputedFields,\n}));\n\nexport default makeSource({\n\tcontentDirPath: \"./content\",\n\tdocumentTypes: [Page, Project],\n\tmdx: {\n\t\tremarkPlugins: [remarkGfm],\n\t\trehypePlugins: [\n\t\t\trehypeSlug,\n\t\t\t[\n\t\t\t\trehypePrettyCode,\n\t\t\t\t{\n\t\t\t\t\ttheme: \"github-dark\",\n\t\t\t\t\tonVisitLine(node) {\n\t\t\t\t\t\t// Prevent lines from collapsing in `display: grid` mode, and allow empty\n\t\t\t\t\t\t// lines to be copy/pasted\n\t\t\t\t\t\tif (node.children.length === 0) {\n\t\t\t\t\t\t\tnode.children = [{ type: \"text\", value: \" \" }];\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tonVisitHighlightedLine(node) {\n\t\t\t\t\t\tnode.properties.className.push(\"line--highlighted\");\n\t\t\t\t\t},\n\t\t\t\t\tonVisitHighlightedWord(node) {\n\t\t\t\t\t\tnode.properties.className = [\"word--highlighted\"];\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\t[\n\t\t\t\trehypeAutolinkHeadings,\n\t\t\t\t{\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tclassName: [\"subheading-anchor\"],\n\t\t\t\t\t\tariaLabel: \"Link to section\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t],\n\t},\n});\n"],
"mappings": ";AAAA,SAAS,oBAAoB,kBAAkB;AAC/C,OAAO,eAAe;AACtB,OAAO,sBAAsB;AAC7B,OAAO,gBAAgB;AACvB,OAAO,4BAA4B;AAGnC,IAAM,iBAAiB;AAAA,EACtB,MAAM;AAAA,IACL,MAAM;AAAA,IACN,SAAS,CAAC,QAAQ,IAAI,IAAI,KAAK;AAAA,EAChC;AAAA,EACA,MAAM;AAAA,IACL,MAAM;AAAA,IACN,SAAS,CAAC,QAAQ,IAAI,KAAK,cAAc,MAAM,GAAG,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG;AAAA,EACtE;AACD;AAEO,IAAM,UAAU,mBAAmB,OAAO;AAAA,EAChD,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,aAAa;AAAA,EAEb,QAAQ;AAAA,IACP,OAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IACX;AAAA,IACA,aAAa;AAAA,MACZ,MAAM;AAAA,MACN,UAAU;AAAA,IACX;AAAA,IACA,MAAM;AAAA,MACL,MAAM;AAAA,IACP;AAAA,IACA,KAAK;AAAA,MACJ,MAAM;AAAA,IACP;AAAA,IACA,YAAY;AAAA,MACX,MAAM;AAAA,IACP;AAAA,EACD;AAAA,EACA;AACD,EAAE;AAEK,IAAM,OAAO,mBAAmB,OAAO;AAAA,EAC7C,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,QAAQ;AAAA,IACP,OAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IACX;AAAA,IACA,aAAa;AAAA,MACZ,MAAM;AAAA,IACP;AAAA,EACD;AAAA,EACA;AACD,EAAE;AAEF,IAAO,8BAAQ,WAAW;AAAA,EACzB,gBAAgB;AAAA,EAChB,eAAe,CAAC,MAAM,OAAO;AAAA,EAC7B,KAAK;AAAA,IACJ,eAAe,CAAC,SAAS;AAAA,IACzB,eAAe;AAAA,MACd;AAAA,MACA;AAAA,QACC;AAAA,QACA;AAAA,UACC,OAAO;AAAA,UACP,YAAY,MAAM;AAGjB,gBAAI,KAAK,SAAS,WAAW,GAAG;AAC/B,mBAAK,WAAW,CAAC,EAAE,MAAM,QAAQ,OAAO,IAAI,CAAC;AAAA,YAC9C;AAAA,UACD;AAAA,UACA,uBAAuB,MAAM;AAC5B,iBAAK,WAAW,UAAU,KAAK,mBAAmB;AAAA,UACnD;AAAA,UACA,uBAAuB,MAAM;AAC5B,iBAAK,WAAW,YAAY,CAAC,mBAAmB;AAAA,UACjD;AAAA,QACD;AAAA,MACD;AAAA,MACA;AAAA,QACC;AAAA,QACA;AAAA,UACC,YAAY;AAAA,YACX,WAAW,CAAC,mBAAmB;AAAA,YAC/B,WAAW;AAAA,UACZ;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD,CAAC;",
"names": []
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
[]

View File

@ -0,0 +1,5 @@
// NOTE This file is auto-generated by Contentlayer
export const allPages = []

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,19 @@
// NOTE This file is auto-generated by Contentlayer
import projects__accessMdx from './projects__access.mdx.json' assert { type: 'json' }
import projects__envshareMdx from './projects__envshare.mdx.json' assert { type: 'json' }
import projects__planetfallMdx from './projects__planetfall.mdx.json' assert { type: 'json' }
import projects__qstashMdx from './projects__qstash.mdx.json' assert { type: 'json' }
import projects__redisQueryMdx from './projects__redis-query.mdx.json' assert { type: 'json' }
import projects__terraformProviderVercelMdx from './projects__terraform-provider-vercel.mdx.json' assert { type: 'json' }
import projects__upstashAuthAnalyticsMdx from './projects__upstash-auth-analytics.mdx.json' assert { type: 'json' }
import projects__upstashCliMdx from './projects__upstash-cli.mdx.json' assert { type: 'json' }
import projects__upstashCoreAnalyticsMdx from './projects__upstash-core-analytics.mdx.json' assert { type: 'json' }
import projects__upstashEdgeFlagsMdx from './projects__upstash-edge-flags.mdx.json' assert { type: 'json' }
import projects__upstashKafkaMdx from './projects__upstash-kafka.mdx.json' assert { type: 'json' }
import projects__upstashQstashSdkMdx from './projects__upstash-qstash-sdk.mdx.json' assert { type: 'json' }
import projects__upstashRatelimitMdx from './projects__upstash-ratelimit.mdx.json' assert { type: 'json' }
import projects__upstashReactUiMdx from './projects__upstash-react-ui.mdx.json' assert { type: 'json' }
import projects__upstashRedisMdx from './projects__upstash-redis.mdx.json' assert { type: 'json' }
export const allProjects = [projects__accessMdx, projects__envshareMdx, projects__planetfallMdx, projects__qstashMdx, projects__redisQueryMdx, projects__terraformProviderVercelMdx, projects__upstashAuthAnalyticsMdx, projects__upstashCliMdx, projects__upstashCoreAnalyticsMdx, projects__upstashEdgeFlagsMdx, projects__upstashKafkaMdx, projects__upstashQstashSdkMdx, projects__upstashRatelimitMdx, projects__upstashReactUiMdx, projects__upstashRedisMdx]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

11
.contentlayer/generated/index.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
// NOTE This file is auto-generated by Contentlayer
import { Page, Project, DocumentTypes } from './types'
export * from './types'
export declare const allPages: Page[]
export declare const allProjects: Project[]
export declare const allDocuments: DocumentTypes[]

View File

@ -0,0 +1,12 @@
// NOTE This file is auto-generated by Contentlayer
export { isType } from 'contentlayer/client'
// NOTE During development Contentlayer imports from `.mjs` files to improve HMR speeds.
// During (production) builds Contentlayer it imports from `.json` files to improve build performance.
import allPages from './Page/_index.json' assert { type: 'json' }
import allProjects from './Project/_index.json' assert { type: 'json' }
export { allPages, allProjects }
export const allDocuments = [...allPages, ...allProjects]

78
.contentlayer/generated/types.d.ts vendored Normal file
View File

@ -0,0 +1,78 @@
// NOTE This file is auto-generated by Contentlayer
import type { Markdown, MDX, ImageFieldData, IsoDateTimeString } from 'contentlayer/core'
import * as Local from 'contentlayer/source-files'
export { isType } from 'contentlayer/client'
export type { Markdown, MDX, ImageFieldData, IsoDateTimeString }
/** Document types */
export type Page = {
/** File path relative to `contentDirPath` */
_id: string
_raw: Local.RawDocumentData
type: 'Page'
title: string
description?: string | undefined
/** MDX file body */
body: MDX
path: string
slug: string
}
export type Project = {
/** File path relative to `contentDirPath` */
_id: string
_raw: Local.RawDocumentData
type: 'Project'
title: string
description: string
date?: IsoDateTimeString | undefined
url?: string | undefined
repository?: string | undefined
/** MDX file body */
body: MDX
path: string
slug: string
}
/** Nested types */
/** Helper types */
export type AllTypes = DocumentTypes | NestedTypes
export type AllTypeNames = DocumentTypeNames | NestedTypeNames
export type DocumentTypes = Page | Project
export type DocumentTypeNames = 'Page' | 'Project'
export type NestedTypes = never
export type NestedTypeNames = never
export interface ContentlayerGenTypes {
documentTypes: DocumentTypes
documentTypeMap: DocumentTypeMap
documentTypeNames: DocumentTypeNames
nestedTypes: NestedTypes
nestedTypeMap: NestedTypeMap
nestedTypeNames: NestedTypeNames
allTypeNames: AllTypeNames
}
declare global {
interface ContentlayerGen extends ContentlayerGenTypes {}
}
export type DocumentTypeMap = {
Page: Page
Project: Project
}
export type NestedTypeMap = {
}

View File

@ -0,0 +1,17 @@
{
"name": "dot-contentlayer",
"description": "This package is auto-generated by Contentlayer",
"version": "0.0.0-KFUTZ636",
"exports": {
"./generated": {
"import": "./generated/index.mjs"
}
},
"typesVersions": {
"*": {
"generated": [
"./generated"
]
}
}
}

View File

@ -0,0 +1,110 @@
"use client";
import { ArrowLeft } from "lucide-react";
import Link from "next/link";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { usePathname } from "next/navigation";
type Props = {
project: {
url?: string;
title: string;
description: string;
repository?: string;
};
};
export const Navigation: React.FC<Props> = ({ project }) => {
const pathname = usePathname();
const ref = useRef<HTMLElement>(null);
const [isIntersecting, setIntersecting] = useState(true);
useEffect(() => {
if (!ref.current) return;
const observer = new IntersectionObserver(([entry]) =>
setIntersecting(entry.isIntersecting),
);
observer.observe(ref.current);
return () => observer.disconnect();
}, []);
return (
<header
ref={ref}
className="bg-gradient-to-tl from-black via-zinc-900 to-black"
>
<div
className={`fixed inset-x-0 top-0 z-50 backdrop-blur lg:backdrop-blur-none duration-200 border-b lg:bg-transparent ${
isIntersecting
? "bg-zinc-900/0 border-transparent"
: "bg-white/10 border-zinc-200 lg:border-transparent"
}`}
>
<div className="container flex flex-row-reverse items-center justify-between p-6 mx-auto">
<div className="flex justify-between gap-8">
<Link
target="_blank"
href="https://github.com/chronark/chronark.com"
>
<span
className={`duration-200 hover:font-medium ${
isIntersecting
? " text-zinc-400 hover:text-zinc-100"
: "text-zinc-600 hover:text-zinc-900"
} `}
>
GitHub
</span>
</Link>
</div>
<Link
href="/projects"
className={`duration-200 hover:font-medium ${
isIntersecting
? " text-zinc-400 hover:text-zinc-100"
: "text-zinc-600 hover:text-zinc-900"
} `}
>
<ArrowLeft className="w-6 h-6 " />
</Link>
</div>
</div>
<div>
<div className="relative px-6 lg:px-8">
<div className="max-w-3xl pt-20 pb-16 mx-auto sm:pt-48">
<div>
<h1 className="text-4xl font-bold uppercase text-zinc-100 sm:text-center sm:text-6xl font-display">
{project.title}
</h1>
<p className="mt-6 text-lg leading-8 text-zinc-400 sm:text-center">
{project.description}{" "}
</p>
</div>
</div>
</div>
<div className="flex items-center justify-center gap-4">
{project.url ? (
<Link
target="_blank"
className="px-4 py-2 font-semibold text-right duration-500 border-b border-transparent text-zinc-200 hover:border-zinc-100"
href={project.url}
>
Website
</Link>
) : null}
{project.repository ? (
<Link
target="_blank"
className="px-4 py-2 font-semibold text-left duration-500 border-b border-transparent text-zinc-200 hover:border-zinc-100"
href={`https://github.com/${project.repository}`}
>
Repository
</Link>
) : null}
</div>
</div>
</header>
);
};

178
app/components/mdx.tsx Normal file
View File

@ -0,0 +1,178 @@
// @ts-nocheck
import * as React from "react";
import Image from "next/image";
import Link from "next/link";
import { useMDXComponent } from "next-contentlayer/hooks";
function clsx(...args: any) {
return args.filter(Boolean).join(" ");
}
const components = {
h1: ({ className, ...props }) => (
<h1
className={clsx(
"mt-2 scroll-m-20 text-4xl font-bold tracking-tight",
className,
)}
{...props}
/>
),
h2: ({ className, ...props }) => (
<h2
className={clsx(
"mt-10 scroll-m-20 border-b border-b-zinc-200 pb-1 text-3xl font-semibold tracking-tight first:mt-0",
className,
)}
{...props}
/>
),
h3: ({ className, ...props }) => (
<h3
className={clsx(
"mt-8 scroll-m-20 text-2xl font-semibold tracking-tight",
className,
)}
{...props}
/>
),
h4: ({ className, ...props }) => (
<h4
className={clsx(
"mt-8 scroll-m-20 text-xl font-semibold tracking-tight",
className,
)}
{...props}
/>
),
h5: ({ className, ...props }) => (
<h5
className={clsx(
"mt-8 scroll-m-20 text-lg font-semibold tracking-tight",
className,
)}
{...props}
/>
),
h6: ({ className, ...props }) => (
<h6
className={clsx(
"mt-8 scroll-m-20 text-base font-semibold tracking-tight",
className,
)}
{...props}
/>
),
a: ({ className, ...props }) => (
<Link
className={clsx(
"font-medium text-zinc-900 underline underline-offset-4",
className,
)}
{...props}
/>
),
p: ({ className, ...props }) => (
<p
className={clsx("leading-7 [&:not(:first-child)]:mt-6", className)}
{...props}
/>
),
ul: ({ className, ...props }) => (
<ul className={clsx("my-6 ml-6 list-disc", className)} {...props} />
),
ol: ({ className, ...props }) => (
<ol className={clsx("my-6 ml-6 list-decimal", className)} {...props} />
),
li: ({ className, ...props }) => (
<li className={clsx("mt-2", className)} {...props} />
),
blockquote: ({ className, ...props }) => (
<blockquote
className={clsx(
"mt-6 border-l-2 border-zinc-300 pl-6 italic text-zinc-800 [&>*]:text-zinc-600",
className,
)}
{...props}
/>
),
img: ({
className,
alt,
...props
}: React.ImgHTMLAttributes<HTMLImageElement>) => (
// eslint-disable-next-line @next/next/no-img-element
<img
className={clsx("rounded-md border border-zinc-200", className)}
alt={alt}
{...props}
/>
),
hr: ({ ...props }) => (
<hr className="my-4 border-zinc-200 md:my-8" {...props} />
),
table: ({ className, ...props }: React.HTMLAttributes<HTMLTableElement>) => (
<div className="w-full my-6 overflow-y-auto">
<table className={clsx("w-full", className)} {...props} />
</div>
),
tr: ({ className, ...props }: React.HTMLAttributes<HTMLTableRowElement>) => (
<tr
className={clsx(
"m-0 border-t border-zinc-300 p-0 even:bg-zinc-100",
className,
)}
{...props}
/>
),
th: ({ className, ...props }) => (
<th
className={clsx(
"border border-zinc-200 px-4 py-2 text-left font-bold [&[align=center]]:text-center [&[align=right]]:text-right",
className,
)}
{...props}
/>
),
td: ({ className, ...props }) => (
<td
className={clsx(
"border border-zinc-200 px-4 py-2 text-left [&[align=center]]:text-center [&[align=right]]:text-right",
className,
)}
{...props}
/>
),
pre: ({ className, ...props }) => (
<pre
className={clsx(
"mt-6 mb-4 overflow-x-auto rounded-lg bg-zinc-900 py-4",
className,
)}
{...props}
/>
),
code: ({ className, ...props }) => (
<code
className={clsx(
"relative rounded border bg-zinc-300 bg-opacity-25 py-[0.2rem] px-[0.3rem] font-mono text-sm text-zinc-600",
className,
)}
{...props}
/>
),
Image,
};
interface MdxProps {
code: string;
}
export function Mdx({ code }: MdxProps) {
const Component = useMDXComponent(code);
return (
<div className="mdx">
<Component components={components} />
</div>
);
}

57
app/components/nav.tsx Normal file
View File

@ -0,0 +1,57 @@
"use client";
import { ArrowLeft } from "lucide-react";
import Link from "next/link";
import React, { useEffect, useRef, useState } from "react";
export const Navigation: React.FC = () => {
const ref = useRef<HTMLElement>(null);
const [isIntersecting, setIntersecting] = useState(true);
useEffect(() => {
if (!ref.current) return;
const observer = new IntersectionObserver(([entry]) =>
setIntersecting(entry.isIntersecting),
);
observer.observe(ref.current);
return () => observer.disconnect();
}, []);
return (
<header ref={ref}>
<div
className={`fixed inset-x-0 top-0 z-50 backdrop-blur duration-200 border-b ${
isIntersecting
? "bg-zinc-900/0 border-transparent"
: "bg-zinc-900/500 border-zinc-800 "
}`}
>
<div className="container flex flex-row-reverse items-center justify-between p-6 mx-auto">
<div className="flex justify-between gap-8">
<Link
href="/projects"
className="duration-200 text-zinc-300 hover:text-zinc-100"
>
<span className="duration-200 text-zinc-300 hover:text-zinc-100">
Projects
</span>
</Link>
<Link
href="/contact"
className="duration-200 text-zinc-300 hover:text-zinc-100"
>
Contact
</Link>
</div>
<Link
href="/"
className="duration-200 text-zinc-300 hover:text-zinc-100"
>
<ArrowLeft className="w-6 h-6 " />
</Link>
</div>
</div>
</header>
);
};

70
app/contact/page.tsx Normal file
View File

@ -0,0 +1,70 @@
"use client";
import { Github, Mail, Twitter } from "lucide-react";
import Link from "next/link";
import { Navigation } from "../components/nav";
const socials = [
{
icon: <Twitter size={20} />,
href: "https://twitter.com/chronark_",
label: "Twitter",
handle: "@chronark_",
},
{
icon: <Mail size={20} />,
href: "mailto:dev@chronark.com",
label: "Email",
handle: "dev@chronark.com",
},
{
icon: <Github size={20} />,
href: "https://github.com/chronark",
label: "Github",
handle: "chronark",
},
];
export default function Example() {
async function submit() {
const res = await fetch("/api/contact", {
method: "POST",
body: JSON.stringify({
name: "John Doe",
email: "",
}),
});
}
return (
<div className=" bg-gradient-to-tl from-zinc-900/0 via-zinc-900 to-zinc-900/0">
<Navigation />
<div className="container flex items-center justify-center min-h-screen px-4 mx-auto">
<div className="grid w-full grid-cols-1 gap-8 mx-auto mt-32 sm:mt-0 sm:grid-cols-3 lg:gap-16">
{socials.map((s) => (
<Link
key={s.href}
href="https://twitter.com/chronark_"
className="relative flex flex-col items-center gap-4 p-8 pb-16 duration-700 border rounded-xl hover:bg-zinc-800/30 group md:gap-8 md:py-24 hover:border-zinc-600 lg:pb-48 border-zinc-700 md:p-16"
>
<span
className="absolute w-px h-2/3 bg-gradient-to-b from-zinc-500 via-zinc-500/50 to-transparent"
aria-hidden="true"
/>
<span className="relative z-10 flex items-center justify-center w-12 h-12 text-sm duration-1000 border rounded-full text-zinc-200 group-hover:text-white group-hover:bg-zinc-900 border-zinc-500 bg-zinc-900 group-hover:border-zinc-200 drop-shadow-orange">
{s.icon}
</span>{" "}
<div className="z-10 flex flex-col items-center">
<span className="text-xl font-medium duration-150 lg:text-3xl text-zinc-200 group-hover:text-white font-display">
{s.handle}
</span>
<span className="mt-4 text-sm text-center duration-1000 text-zinc-400 group-hover:text-zinc-200">
{s.label}
</span>
</div>
</Link>
))}
</div>
</div>
</div>
);
}

View File

@ -3,41 +3,40 @@ import Link from "next/link";
import React from "react"; import React from "react";
const navigation = [ const navigation = [
{ name: "Home", href: "/" }, // { name: "About", href: "/about" },
{ name: "About", href: "/about" },
{ name: "Projects", href: "/projects" }, { name: "Projects", href: "/projects" },
{ name: "Blog", href: "/blog" }, // { name: "Blog", href: "/blog" },
{ name: "Contact", href: "/contact" }, { name: "Contact", href: "/contact" },
]; ];
export default function Home() { export default function Home() {
return ( return (
<div className="w-screen h-screen flex overflow-hidden flex-col items-center justify-center bg-gradient-to-tl from-black via-zinc-400/10 to-black"> <div className="flex flex-col items-center justify-center w-screen h-screen overflow-hidden bg-gradient-to-tl from-black via-zinc-400/10 to-black">
<nav className="my-16 animate-fade-in"> <nav className="my-16 animate-fade-in">
<ul className="flex items-center justify-center gap-4"> <ul className="flex items-center justify-center gap-4">
{navigation.map((item) => ( {navigation.map((item) => (
<Link <Link
key={item.href} key={item.href}
href={item.href} href={item.href}
className="text-zinc-500 text-sm hover:text-zinc-300 duration-500" className="text-sm duration-500 text-zinc-500 hover:text-zinc-300"
> >
{item.name} {item.name}
</Link> </Link>
))} ))}
</ul> </ul>
</nav> </nav>
<div className="hidden animate-glow md:block w-screen animate-fade-left h-px bg-gradient-to-r from-zinc-300/0 via-zinc-300/50 to-zinc-300/0" /> <div className="hidden w-screen h-px animate-glow md:block animate-fade-left bg-gradient-to-r from-zinc-300/0 via-zinc-300/50 to-zinc-300/0" />
<h1 className="text-edge-outline cursor-default animate-title z-10 hover:text-zinc-50 duration-1000 font-display text-4xl sm:text-6xl md:text-9xl whitespace-nowrap bg-clip-text bg-zinc-200 font-black text-transparent "> <h1 className="z-10 text-4xl font-black text-transparent duration-1000 cursor-default text-edge-outline animate-title hover:text-zinc-50 font-display sm:text-6xl md:text-9xl whitespace-nowrap bg-clip-text bg-zinc-200 ">
CHRONARK CHRONARK
</h1> </h1>
<div className="hidden animate-glow md:block w-screen animate-fade-right h-px bg-gradient-to-r from-zinc-300/0 via-zinc-300/50 to-zinc-300/0" /> <div className="hidden w-screen h-px animate-glow md:block animate-fade-right bg-gradient-to-r from-zinc-300/0 via-zinc-300/50 to-zinc-300/0" />
<div className="my-16 animate-fade-in text-center"> <div className="my-16 text-center animate-fade-in">
<h2 className="text-zinc-500 text-sm "> <h2 className="text-sm text-zinc-500 ">
Hi, I'm building serverless and open source solutions at{" "} Hi, I'm building serverless and open source solutions at{" "}
<Link <Link
href="https://upstash.com" href="https://upstash.com"
className="underline hover:text-zinc-300 duration-500" className="underline duration-500 hover:text-zinc-300"
> >
Upstash Upstash
</Link> </Link>
@ -46,7 +45,7 @@ export default function Home() {
and{" "} and{" "}
<Link <Link
href="https://planetfall.io" href="https://planetfall.io"
className="underline hover:text-zinc-300 duration-500" className="underline duration-500 hover:text-zinc-300"
> >
planetfall.io planetfall.io
</Link>{" "} </Link>{" "}

View File

@ -0,0 +1,32 @@
[data-rehype-pretty-code-fragment] code {
@apply grid min-w-full break-words rounded-none border-0 bg-transparent p-0 text-sm text-black;
counter-reset: line;
box-decoration-break: clone;
}
[data-rehype-pretty-code-fragment] .line {
@apply px-4 py-1;
}
[data-rehype-pretty-code-fragment] [data-line-numbers] > .line::before {
counter-increment: line;
content: counter(line);
display: inline-block;
width: 1rem;
margin-right: 1rem;
text-align: right;
color: gray;
}
[data-rehype-pretty-code-fragment] .line--highlighted {
@apply bg-zinc-300 bg-opacity-10;
}
[data-rehype-pretty-code-fragment] .line-highlighted span {
@apply relative;
}
[data-rehype-pretty-code-fragment] .word--highlighted {
@apply rounded-md bg-zinc-300 bg-opacity-10 p-1;
}
[data-rehype-pretty-code-title] {
@apply mt-4 py-2 px-4 text-sm font-medium;
}
[data-rehype-pretty-code-title] + pre {
@apply mt-0;
}

View File

@ -0,0 +1,41 @@
import { notFound } from "next/navigation";
import { allProjects } from "contentlayer/generated";
import { Mdx } from "@/app/components/mdx";
import { Navigation } from "@/app/components/article-nav";
import "./mdx.css";
import Link from "next/link";
interface PostPageProps {
params: {
slug: string;
};
}
export async function generateStaticParams(): Promise<
PostPageProps["params"][]
> {
return allProjects.map((p) => ({
slug: p.slug,
}));
}
export default async function PostPage({ params }: PostPageProps) {
const slug = params?.slug;
const project = allProjects.find((project) => project.slug === slug);
if (!project) {
notFound();
}
return (
<div className="min-h-screen bg-white ">
<Navigation project={project} />
<main className=" bg-zinc-50">
<article className="px-4 py-12 mx-auto prose text-zinc-600 ">
<Mdx code={project.body.code} />
</article>
</main>
</div>
);
}

View File

@ -1,138 +0,0 @@
const stats = [
{ label: "Founded", value: "2021" },
{ label: "Employees", value: "37" },
{ label: "Countries", value: "12" },
{ label: "Raised", value: "$25M" },
];
export default function Example() {
return (
<div className="py-24 sm:py-32">
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto grid max-w-2xl grid-cols-1 items-start gap-y-16 gap-x-8 sm:gap-y-24 lg:mx-0 lg:max-w-none lg:grid-cols-2">
<div className="lg:pr-4">
<div className="relative overflow-hidden rounded-3xl bg-gray-900 px-6 pb-9 pt-64 shadow-2xl sm:px-12 lg:max-w-lg lg:px-8 lg:pb-8 xl:px-10 xl:pb-10">
<img
className="absolute inset-0 h-full w-full object-cover brightness-125 saturate-0"
src="https://images.unsplash.com/photo-1630569267625-157f8f9d1a7e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80"
alt=""
/>
<div className="absolute inset-0 bg-gray-900 mix-blend-multiply" />
<svg
viewBox="0 0 1097 845"
aria-hidden="true"
className="absolute top-1/2 left-1/2 -ml-16 w-[68.5625rem] -translate-x-1/2 -translate-y-1/2 transform-gpu blur-3xl"
>
<path
fill="url(#e7ccf164-908d-46dd-9194-2f8a16ad5a93)"
fillOpacity=".4"
d="M301.174 646.641 193.541 844.786 0 546.172l301.174 100.469 193.845-356.855c1.241 164.891 42.802 431.935 199.124 180.978 195.402-313.696 143.295-588.18 284.729-419.266 113.148 135.13 124.068 367.989 115.378 467.527L811.753 372.553l20.102 451.119-530.681-177.031Z"
/>
<defs>
<linearGradient
id="e7ccf164-908d-46dd-9194-2f8a16ad5a93"
x1="1097.04"
x2="-141.165"
y1=".22"
y2="363.075"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#776FFF" />
<stop offset={1} stopColor="#FF4694" />
</linearGradient>
</defs>
</svg>
<figure className="relative isolate">
<svg
viewBox="0 0 162 128"
fill="none"
aria-hidden="true"
className="absolute -top-4 -left-2 -z-10 h-32 stroke-white/20"
>
<path
id="0ef284b8-28c2-426e-9442-8655d393522e"
d="M65.5697 118.507L65.8918 118.89C68.9503 116.314 71.367 113.253 73.1386 109.71C74.9162 106.155 75.8027 102.28 75.8027 98.0919C75.8027 94.237 75.16 90.6155 73.8708 87.2314C72.5851 83.8565 70.8137 80.9533 68.553 78.5292C66.4529 76.1079 63.9476 74.2482 61.0407 72.9536C58.2795 71.4949 55.276 70.767 52.0386 70.767C48.9935 70.767 46.4686 71.1668 44.4872 71.9924L44.4799 71.9955L44.4726 71.9988C42.7101 72.7999 41.1035 73.6831 39.6544 74.6492C38.2407 75.5916 36.8279 76.455 35.4159 77.2394L35.4047 77.2457L35.3938 77.2525C34.2318 77.9787 32.6713 78.3634 30.6736 78.3634C29.0405 78.3634 27.5131 77.2868 26.1274 74.8257C24.7483 72.2185 24.0519 69.2166 24.0519 65.8071C24.0519 60.0311 25.3782 54.4081 28.0373 48.9335C30.703 43.4454 34.3114 38.345 38.8667 33.6325C43.5812 28.761 49.0045 24.5159 55.1389 20.8979C60.1667 18.0071 65.4966 15.6179 71.1291 13.7305C73.8626 12.8145 75.8027 10.2968 75.8027 7.38572C75.8027 3.6497 72.6341 0.62247 68.8814 1.1527C61.1635 2.2432 53.7398 4.41426 46.6119 7.66522C37.5369 11.6459 29.5729 17.0612 22.7236 23.9105C16.0322 30.6019 10.618 38.4859 6.47981 47.558L6.47976 47.558L6.47682 47.5647C2.4901 56.6544 0.5 66.6148 0.5 77.4391C0.5 84.2996 1.61702 90.7679 3.85425 96.8404L3.8558 96.8445C6.08991 102.749 9.12394 108.02 12.959 112.654L12.959 112.654L12.9646 112.661C16.8027 117.138 21.2829 120.739 26.4034 123.459L26.4033 123.459L26.4144 123.465C31.5505 126.033 37.0873 127.316 43.0178 127.316C47.5035 127.316 51.6783 126.595 55.5376 125.148L55.5376 125.148L55.5477 125.144C59.5516 123.542 63.0052 121.456 65.9019 118.881L65.5697 118.507Z"
/>
<use href="#0ef284b8-28c2-426e-9442-8655d393522e" x={86} />
</svg>
<img
src="https://tailwindui.com/img/logos/workcation-logo-white.svg"
alt=""
className="h-12 w-auto"
/>
<blockquote className="mt-6 text-xl font-semibold leading-8 text-white">
<p>
Amet amet eget scelerisque tellus sit neque faucibus non
eleifend. Integer eu praesent at a. Ornare arcu gravida
natoque erat et cursus tortor.
</p>
</blockquote>
<figcaption className="mt-6 text-sm leading-6 text-gray-300">
<strong className="font-semibold text-white">
Judith Rogers,
</strong>{" "}
CEO at Workcation
</figcaption>
</figure>
</div>
</div>
<div>
<div className="text-base leading-7 text-gray-700 lg:max-w-lg">
<p className="text-base font-semibold leading-7 text-indigo-600">
Company values
</p>
<h1 className="mt-2 text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
On a mission to empower remote teams
</h1>
<div className="max-w-xl">
<p className="mt-6">
Faucibus commodo massa rhoncus, volutpat. Dignissim sed eget
risus enim. Mattis mauris semper sed amet vitae sed turpis id.
Id dolor praesent donec est. Odio penatibus risus viverra
tellus varius sit neque erat velit. Faucibus commodo massa
rhoncus, volutpat. Dignissim sed eget risus enim. Mattis
mauris semper sed amet vitae sed turpis id.
</p>
<p className="mt-8">
Et vitae blandit facilisi magna lacus commodo. Vitae sapien
duis odio id et. Id blandit molestie auctor fermentum
dignissim. Lacus diam tincidunt ac cursus in vel. Mauris
varius vulputate et ultrices hac adipiscing egestas. Iaculis
convallis ac tempor et ut. Ac lorem vel integer orci.
</p>
<p className="mt-8">
Et vitae blandit facilisi magna lacus commodo. Vitae sapien
duis odio id et. Id blandit molestie auctor fermentum
dignissim. Lacus diam tincidunt ac cursus in vel. Mauris
varius vulputate et ultrices hac adipiscing egestas. Iaculis
convallis ac tempor et ut. Ac lorem vel integer orci.
</p>
</div>
</div>
<dl className="mt-10 grid grid-cols-2 gap-8 border-t border-gray-900/10 pt-10 sm:grid-cols-4">
{stats.map((stat, statIdx) => (
<div key={statIdx}>
<dt className="text-sm font-semibold leading-6 text-gray-600">
{stat.label}
</dt>
<dd className="mt-2 text-3xl font-bold leading-10 tracking-tight text-gray-900">
{stat.value}
</dd>
</div>
))}
</dl>
<div className="mt-10 flex">
<a
href="#"
className="text-base font-semibold leading-7 text-indigo-600"
>
Learn more about our company{" "}
<span aria-hidden="true">&rarr;</span>
</a>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@ -2,7 +2,7 @@ export default function ProjectsLayout({
children, children,
}: { children: React.ReactNode }) { }: { children: React.ReactNode }) {
return ( return (
<div className="bg-gradient-to-tl min-h-screen from-zinc-900 via-zinc-400/10 to-zinc-900"> <div className="relative min-h-screen bg-gradient-to-tl from-zinc-900 via-zinc-400/10 to-zinc-900 ">
{children} {children}
</div> </div>
); );

View File

@ -1,155 +1,15 @@
import Link from "next/link"; import Link from "next/link";
import React from "react"; import React from "react";
import { allProjects, Project } from "contentlayer/generated";
type Project = { import { Navigation } from "../components/nav";
slug: string;
title: string;
description: string;
href: string;
date?: string;
};
const projects: Project[] = [
{
slug: "upstash-kafka",
title: "@upstash/kafka",
href: "https://github.com/upstash/upstash-kafka",
description:
"A fully typed Kafka client built for Upstash Kafka and HTTP, perfect for serverless and edge runtimes.",
date: "2022-01-08",
},
{
slug: "upstash-redis",
title: "@upstash/redis",
href: "https://github.com/upstash/upstash-redis",
description:
"A fully typed Redis client built for Upstash Redis and HTTP, perfect for serverless and edge runtimes.",
date: "2022-03-14",
},
{
slug: "upstash-redis",
title: "@upstash/ratelimit",
href: "https://github.com/upstash/ratelimit",
description:
"Ratelimiting library for serverless and edge runtimes. Built on top of Upstash Redis.",
date: "2020-06-06",
},
{
slug: "upstash-edge-flags",
title: "@upstash/edge-flags",
href: "https://github.com/upstash/edge-flags",
description: "Feature flags for edge functions.",
date: "2022-12-12",
},
{
slug: "upstash-cli",
title: "@upstash/cli",
href: "https://github.com/upstash/cli",
description:
"A CLI to provision and manage Upstash resources, including Redis and Kafka databases.",
date: "2022-05-16",
},
{
slug: "upstash-react-ui",
title: "@upstash/react-cli",
href: "https://github.com/upstash/react-ui",
description:
"A CLI React component to interact with Upstash Redis databases.",
date: "2023-02-05",
},
{
slug: "qstash",
title: "QStash",
href: "https://upstash.com/qstash",
description:
"QStash is a fully managed serverless queue and messaging service designed for the serverless era.",
date: "2022-07-18",
},
{
slug: "upstash-qstash-sdk",
title: "@upstash/qstash",
href: "https://github.com/upstash/sdk-qstash-ts",
description: "A typescript client and consumer for QStash.",
date: "2020-07-18",
},
{
slug: "upstash-core-analytics",
title: "@upstash/core-analytics",
href: "https://github.com/upstash/core-analytics",
description:
"Low level utilities to build analytics tools on top of Redis.",
date: "2023-02-13",
},
{
slug: "upstash-auth-analytics",
title: "@upstash/auth-analytics",
href: "https://github.com/upstash/auth-analytics",
description: "A library to record and analyse Auth.js user behaviour",
},
{
slug: "upstash-web-analytics",
title: "@upstash/web-analytics",
href: "https://github.com/upstash/auth-analytics",
description:
"A library to record and analyse web page traffic and user behaviour",
date: "2020-03-16",
},
{
slug: "upstash-ratelimit-analytics",
title: "Ratelimit Analytics",
href: "https://github.com/upstash/ratelimit",
description:
"Near realtime analytics for your ratelimits. Integrated into the @upstash/ratelimit library.",
date: "2023-03-01",
},
{
slug: "planetfall",
title: "Planetfall",
href: "https://planetfall.io",
description:
"I'm building a SAAS, that provides global latency monitoring for your APIs and websites from edge locations around the world. Have you ever wondered how fast your API is in any part of the world? Planetfall allows you to find out and monitor it continuously.",
date: "2023-04-01",
},
{
slug: "terraform-provider-vercel",
title: "Vercel Terraform Provider",
href: "https://github.com/chronark/terraform-provider-vercel",
description:
"A Terraform provider for Vercel. It has been deprecated it when Vercel rolled out their official provider.",
date: "2021-03-16",
},
{
slug: "envshare",
title: "EnvShare",
href: "https://envshare.dev",
description:
"EnvShare is a simple tool to share environment variables securely. It uses AES-GCM to encrypt your data before sending it to the server. The encryption key never leaves your browser.",
date: "2023-01-16",
},
{
slug: "redis-query",
title: "Redis Query",
href: "https://github.com/chronark/redis-query",
description:
"Client side secondary indexing for Redis. It allows you to query your Redis data efficiently. Inspired by FaunaDB indices.",
date: "2023-02-16",
},
{
slug: "access",
title: "@chronark/access",
href: "https://github.com/chronark/access",
description:
"A minimal library for access control. It is designed to be used together with opaque access tokens by providing a simple interface to define roles with different access permissions and verifying requests to resources.",
date: "2022-11-13",
},
];
export default function ProjectsPage() { export default function ProjectsPage() {
const featured = projects.find((project) => project.slug === "planetfall")!; const featured = allProjects.find(
const top2 = projects.find((project) => project.slug === "envshare")!; (project) => project.slug === "planetfall",
const top3 = projects.find((project) => project.slug === "qstash")!; )!;
const top2 = allProjects.find((project) => project.slug === "envshare")!;
const sorted = projects const top3 = allProjects.find((project) => project.slug === "qstash")!;
const sorted = allProjects
.filter( .filter(
(project) => (project) =>
project.slug !== featured.slug && project.slug !== featured.slug &&
@ -163,24 +23,25 @@ export default function ProjectsPage() {
); );
return ( return (
<div className="py-24 sm:py-32"> <div className="relative">
<div className="mx-auto max-w-7xl px-6 lg:px-8 space-y-8 md:space-y-16"> <Navigation />
<div className="mx-auto max-w-2xl lg:mx-0"> <div className="px-6 pt-16 mx-auto space-y-8 max-w-7xl lg:px-8 md:space-y-16 md:pt-24 lg:pt-32">
<div className="max-w-2xl mx-auto lg:mx-0">
<h2 className="text-3xl font-bold tracking-tight text-zinc-100 sm:text-4xl"> <h2 className="text-3xl font-bold tracking-tight text-zinc-100 sm:text-4xl">
Projects Projects
</h2> </h2>
<p className="text-zinc-400 mt-4"> <p className="mt-4 text-zinc-400">
Some of the projects are from work and some are on my own time. Some of the projects are from work and some are on my own time.
</p> </p>
</div> </div>
<div className="w-full h-px bg-zinc-800" /> <div className="w-full h-px bg-zinc-800" />
<div className="mx-auto grid grid-cols-1 gap-8 lg:grid-cols-2 "> <div className="grid grid-cols-1 gap-8 mx-auto lg:grid-cols-2 ">
<article className="mx-auto w-full max-w-2xl lg:mx-0 lg:max-w-lg"> <article className="w-full max-w-2xl mx-auto lg:mx-0 lg:max-w-lg">
<div className="text-zinc-100 text-xs"> <div className="text-xs text-zinc-100">
{featured.date ? ( {featured.date ? (
<time dateTime={new Date(featured.date).toISOString()}> <time dateTime={new Date(featured.date).toISOString()}>
{featured.date} {new Date(featured.date).toDateString()}
</time> </time>
) : ( ) : (
<span>SOON</span> <span>SOON</span>
@ -188,11 +49,11 @@ export default function ProjectsPage() {
</div> </div>
<h2 <h2
id="featured-post" id="featured-post"
className="mt-4 text-3xl font-bold tracking-tight text-zinc-100 group-hover:text-white sm:text-4xl" className="mt-4 text-3xl font-bold tracking-tight text-zinc-100 group-hover:text-white sm:text-4xl font-display"
> >
{featured.title} {featured.title}
</h2> </h2>
<p className="mt-4 text-lg leading-8 text-zinc-400 duration-150 group-hover:text-zinc-300"> <p className="mt-4 leading-8 duration-150 text-zinc-400 group-hover:text-zinc-300">
{featured.description} {featured.description}
</p> </p>
<div className="mt-4"> <div className="mt-4">
@ -204,15 +65,15 @@ export default function ProjectsPage() {
</Link> </Link>
</div> </div>
</article> </article>
<div className="mx-auto w-full max-w-2xl flex flex-col gap-8 border-t border-gray-900/10 pt-12 sm:pt-16 lg:mx-0 lg:max-w-none lg:border-t-0 lg:pt-0"> <div className="flex flex-col w-full max-w-2xl gap-8 pt-12 mx-auto border-t border-gray-900/10 sm:pt-16 lg:mx-0 lg:max-w-none lg:border-t-0 lg:pt-0">
{[top2, top3].map((project) => ( {[top2, top3].map((project) => (
<Card key={project.slug} project={project} /> <Card key={project.slug} project={project} />
))} ))}
</div> </div>
</div> </div>
<div className="w-full hidden md:block h-px bg-zinc-800" /> <div className="hidden w-full h-px md:block bg-zinc-800" />
<div className="mx-auto grid max-w-2xl grid-cols-1 gap-4 lg:mx-0 lg:max-w-none md:grid-cols-2 lg:grid-cols-3"> <div className="grid max-w-2xl grid-cols-1 gap-4 mx-auto lg:mx-0 lg:max-w-none md:grid-cols-2 lg:grid-cols-3">
{sorted.map((project) => ( {sorted.map((project) => (
<Card key={project.slug} project={project} /> <Card key={project.slug} project={project} />
))} ))}
@ -235,21 +96,21 @@ const Card: React.FC<{ project: Project; border?: boolean }> = ({
: "" : ""
} `} } `}
> >
<div className="text-zinc-100 text-xs"> <div className="text-xs text-zinc-100">
{project.date ? ( {project.date ? (
<time dateTime={new Date(project.date).toISOString()}> <time dateTime={new Date(project.date).toISOString()}>
{project.date} {new Date(project.date).toDateString()}
</time> </time>
) : ( ) : (
<span>SOON</span> <span>SOON</span>
)} )}
</div> </div>
<div className=" relative duration-150"> <div className="relative duration-150 ">
<h3 className="mt-3 text-lg font-semibold leading-6 text-zinc-100 group-hover:text-white "> <h3 className="mt-3 text-lg font-semibold leading-6 text-zinc-100 group-hover:text-white font-display ">
<span className="absolute inset-0" /> <span className="absolute inset-0" />
{project.title} {project.title}
</h3> </h3>
<p className="mt-5 text-sm leading-6 text-zinc-400 line-clamp-3 duration-150 group-hover:text-zinc-300"> <p className="mt-5 text-sm leading-6 duration-150 text-zinc-400 line-clamp-3 group-hover:text-zinc-300">
{project.description} {project.description}
</p> </p>
</div> </div>

View File

@ -0,0 +1,9 @@
---
title: "@chronark/access"
description: A minimal library for access control. It is designed to be used together with opaque access tokens by providing a simple interface to define roles with different access permissions and verifying requests to resources.
repository: chronark/access
date: "2022-11-13"
---
TODO:

View File

@ -0,0 +1,116 @@
---
title: envshare.dev
description: EnvShare is a simple tool to share environment variables securely. It uses AES-GCM to encrypt your data before sending it to the server. The encryption key never leaves your browser.
date: "2023-01-16"
url: https://envshare.dev
repository: chronark/envshare
---
EnvShare is a simple tool to share environment variables securely. It uses
**AES-GCM** to encrypt your data before sending it to the server. The encryption
key never leaves your browser.
## Features
- **Shareable Links:** Share your environment variables securely by sending a
link
- **End-to-End Encryption:** AES-GCM encryption is used to encrypt your data
before sending it to the server
- **Limit number of reads:** Limit the number of times a link can be read
- **Auto Expire:** Automatically expire links and delete data after a certain
time
![](img/envshare.png)
## Built with
- [Next.js](https://nextjs.org)
- [tailwindcss](https://tailwindcss.com)
- Deployed on [Vercel](https://vercel.com?utm_source=envshare)
- Data stored on [Upstash](https://upstash.com?utm_source=envshare)
## Deploy your own
Detailed instructions can be found [here](https://envshare.dev/deploy)
All you need is a Redis database on Upstash and a Vercel account. Click the
button below to clone and deploy:
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?demo-title=EnvShare&demo-description=Simple%20Next.js%20%2B%20Upstash%20app%20to%20share%20environment%20variables%20securely%20using%20AES-GCM%20encryption.&demo-url=https%3A%2F%2Fenvshare.dev%2F&demo-image=%2F%2Fimages.ctfassets.net%2Fe5382hct74si%2F5SaFBHXp5FBFJbsTzVqIJ3%2Ff0f8382369b7642fd8103debb9025c11%2Fenvshare.png&project-name=EnvShare&repository-name=envshare&repository-url=https%3A%2F%2Fgithub.com%2Fchronark%2Fenvshare&from=templates&integration-ids=oac_V3R1GIpkoJorr6fqyiwdhl17)
## Configuration
### Environment Variables
`ENABLE_VERCEL_ANALYTICS` Any truthy value will enable Vercel Analytics. This is turned off by default
## Contributing
This repository uses `pnpm` to manage dependencies. Install it using
`npm install -g pnpm`
Please run `pnpm fmt` before committing to format the code.
## Docs
Docs in the README are temporary and will be moved to the website soon.
### API
#### Store a secret
**PLEASE NEVER EVER UPLOAD UNENCRYPTED SECRETS.**
This endpoint is only meant to store **already encrypted** secrets. The
encrypted secrets are stored in plain text.
```sh-session
$ curl -XPOST -s https://envshare.dev/api/v1/secret -d "already-encrypted-secret"
```
You can add optional headers to configure the ttl and number of reads.
```sh-session
$ curl -XPOST -s https://envshare.dev/api/v1/secret -d "already-encrypted-secret" -H "envshare-ttl: 3600" -H "envshare-reads: 10"
```
- Omitting the `envshare-ttl` header will set a default of 30 days. Disable the
ttl by setting it to 0. (`envshare-ttl: 0`)
- Omitting the `envshare-reads` header will simply disable it and allow reading
for an unlimited number of times.
This endpoint returns a JSON response with the secret id:
```json
{
"data": {
"id": "HdPbXgpvUvNk43oxSdK97u",
"ttl": 86400,
"reads": 2,
"expiresAt": "2023-01-19T20:47:28.383Z",
"url": "http://envshare.dev/api/v1/secret/HdPbXgpvUvNk43oxSdK97u"
}
}
```
#### Retrieve a secret
You need an id to retrieve a secret. The id is returned when you store a secret.
```sh-session
$ curl -s https://envshare.dev/api/v1/secret/HdPbXgpvUvNk43oxSdK97u
```
```json
{
"data": {
"secret": "Hello",
"remainingReads": 1
}
}
```

View File

@ -0,0 +1,8 @@
---
title: Planetfall
description: I'm building a SAAS, that provides global latency monitoring for your APIs and websites from edge locations around the world. Have you ever wondered how fast your API is in any part of the world? Planetfall allows you to find out and monitor it continuously.
date: "2023-04-01"
url: https://planetfall.io
---
TODO:

View File

@ -0,0 +1,9 @@
---
title: QStash
description: QStash is a fully managed serverless queue and messaging service designed for the serverless era.
date: "2022-07-18"
url: https://upstash.com/qstash
---
TODO:

View File

@ -0,0 +1,8 @@
---
title: Redis Query
description: Client side secondary indexing for Redis. It allows you to query your Redis data efficiently. Inspired by FaunaDB indices.
repository: chronark/redis-query
---
TODO:

View File

@ -0,0 +1,7 @@
---
title: Vercel Terraform Provider
description: A Terraform provider for Vercel. It has been deprecated it when Vercel rolled out their official provider.
date: "2021-03-16"
repository: chronark/terraform-provider-vercel
---
TODO:

View File

@ -0,0 +1,9 @@
---
title: Upstash Auth Analytics
description: A library to record and analyse Auth.js user behaviour
url: https://console.upstash.com/ratelimit
repository: upstash/auth-analytics
---
TODO:

View File

@ -0,0 +1,10 @@
---
title: "@upstash/cli"
description: A CLI to provision and manage Upstash resources, including Redis and Kafka databases.
date: "2022-05-16"
url: https://upstash.com/cli
repository: upstash/cli
---
TODO:

View File

@ -0,0 +1,10 @@
---
title: Upstash Core Analytics
description: Low level utilities to build analytics tools on top of Redis.
date: "2023-02-13"
url: https://console.upstash.com/ratelimit
repository: upstash/core-analytics
---
TODO:

View File

@ -0,0 +1,10 @@
---
title: "@upstash/edge-flags"
description: Featues flags for your edge functions.
date: "2022-12-12"
url: https://upstash.com/edge-flags
repository: upstash/edge-flags
---
TODO:

View File

@ -0,0 +1,10 @@
---
title: "@upstash/kafka"
description: A fully typed Kafka client built for Upstash Kafka and HTTP, perfect for serverless and edge runtimes
date: "2022-01-08"
url: https://upstash.com/kafka
repository: upstash/upstash-kafka
---
TODO:

View File

@ -0,0 +1,9 @@
---
title: "@upstash/qstash"
description: A typescript client and consumer for QStash.
date: "2022-07-18"
url: https://upstash.com/qstash
repository: upstash/sdk-qstash-ts
---
TODO:

View File

@ -0,0 +1,10 @@
---
title: Upstash Ratelimit Analytics
description: Near realtime analytics for your ratelimits. Integrated into the @upstash/ratelimit library.
repository: upstash/ratelimit
date: "2023-03-01"
website: https://console.upstash.com/ratelimit
---
TODO:

View File

@ -0,0 +1,10 @@
---
title: "@upstash/ratelimit"
description: Ratelimiting library for serverless and edge runtimes. Built on top of Upstash Redis.
date: "2022-06-06"
url: https://upstash.com/ratelimit
repository: upstash/ratelimit
---
TODO:

View File

@ -0,0 +1,10 @@
---
title: React.js CLI
description: A CLI React component to interact with Upstash Redis databases.
date: "2023-02-05"
url: https://upstash.com
repository: upstash/react-ui
---
TODO:

View File

@ -0,0 +1,10 @@
---
title: "@upstash/redis"
description: A fully typed Redis client built for Upstash Redis and HTTP, perfect for serverless and edge runtimes.
date: "2022-03-14"
url: https://upstash.com/redis
repository: upstash/upstash-redis
---
TODO:

View File

@ -0,0 +1,8 @@
---
title: Upstash Web Analytics
description: A library to record and analyse web page traffic and user behaviour
repository: upstash/web-analytics
---
TODO:

99
contentlayer.config.js Normal file
View File

@ -0,0 +1,99 @@
import { defineDocumentType, makeSource } from "contentlayer/source-files";
import remarkGfm from "remark-gfm";
import rehypePrettyCode from "rehype-pretty-code";
import rehypeSlug from "rehype-slug";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
/** @type {import('contentlayer/source-files').ComputedFields} */
const computedFields = {
path: {
type: "string",
resolve: (doc) => `/${doc._raw.flattenedPath}`,
},
slug: {
type: "string",
resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/"),
},
};
export const Project = defineDocumentType(() => ({
name: "Project",
filePathPattern: "./projects/**/*.mdx",
contentType: "mdx",
fields: {
title: {
type: "string",
required: true,
},
description: {
type: "string",
required: true,
},
date: {
type: "date",
},
url: {
type: "string",
},
repository: {
type: "string",
},
},
computedFields,
}));
export const Page = defineDocumentType(() => ({
name: "Page",
filePathPattern: "pages/**/*.mdx",
contentType: "mdx",
fields: {
title: {
type: "string",
required: true,
},
description: {
type: "string",
},
},
computedFields,
}));
export default makeSource({
contentDirPath: "./content",
documentTypes: [Page, Project],
mdx: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
rehypeSlug,
[
rehypePrettyCode,
{
theme: "github-dark",
onVisitLine(node) {
// Prevent lines from collapsing in `display: grid` mode, and allow empty
// lines to be copy/pasted
if (node.children.length === 0) {
node.children = [{ type: "text", value: " " }];
}
},
onVisitHighlightedLine(node) {
node.properties.className.push("line--highlighted");
},
onVisitHighlightedWord(node) {
node.properties.className = ["word--highlighted"];
},
},
],
[
rehypeAutolinkHeadings,
{
properties: {
className: ["subheading-anchor"],
ariaLabel: "Link to section",
},
},
],
],
},
});

17
mdx-components.tsx Normal file
View File

@ -0,0 +1,17 @@
import { PropsWithChildren } from "react";
// This file is required to use MDX in `app` directory.
export function useMDXComponents(components: any): any {
return {
// Allows customizing built-in components, e.g. to add styling.
h1: ({ children }: PropsWithChildren) => (
<h1 className="mt-2 text-3xl font-bold tracking-tight text-zinc-100 md:text-center sm:text-4xl">
{children}
</h1>
),
h2: ({ children }: PropsWithChildren) => (
<h2 className="text-zinc-50">{children}</h2>
),
...components,
};
}

View File

@ -1,11 +0,0 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
appDir: true,
},
images: {
domains: ["pbs.twimg.com"],
},
};
module.exports = nextConfig;

15
next.config.mjs Normal file
View File

@ -0,0 +1,15 @@
import { withContentlayer } from "next-contentlayer";
/** @type {import('next').NextConfig} */
const nextConfig = {
pageExtensions: ["js", "jsx", "ts", "tsx", "md", "mdx"],
experimental: {
appDir: true,
mdxRs: true,
},
images: {
domains: ["pbs.twimg.com"],
},
};
export default withContentlayer(nextConfig);

View File

@ -10,14 +10,22 @@
}, },
"dependencies": { "dependencies": {
"@next/font": "^13.2.1", "@next/font": "^13.2.1",
"@next/mdx": "^13.2.1",
"@types/node": "18.14.1", "@types/node": "18.14.1",
"@types/react": "18.0.28", "@types/react": "18.0.28",
"@types/react-dom": "18.0.11", "@types/react-dom": "18.0.11",
"@vercel/analytics": "^0.1.10", "@vercel/analytics": "^0.1.10",
"contentlayer": "^0.3.0",
"lucide-react": "^0.115.0", "lucide-react": "^0.115.0",
"markdown-wasm": "^1.2.0",
"next": "13.2.1", "next": "13.2.1",
"next-contentlayer": "^0.3.0",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-pretty-code": "^0.9.4",
"rehype-slug": "^5.1.0",
"remark-gfm": "^3.0.1",
"typescript": "4.9.5" "typescript": "4.9.5"
}, },
"devDependencies": { "devDependencies": {

2525
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@ const defaultTheme = require("tailwindcss/defaultTheme");
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: ["./app/**/*.{js,ts,jsx,tsx}"], content: ["./app/**/*.{js,ts,jsx,tsx}", "./mdx-components.tsx"],
theme: { theme: {
extend: { extend: {

View File

@ -21,7 +21,9 @@
], ],
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": ["./*"] "@/*": ["./*"],
"contentlayer/generated": ["./.contentlayer/generated"]
} }
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],

5
types/mdx.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
// types/mdx.d.ts
declare module "*.mdx" {
let MDXComponent: (props) => JSX.Element;
export default MDXComponent;
}