diff --git a/.all-contributorsrc b/.all-contributorsrc
new file mode 100644
index 0000000..539d10b
--- /dev/null
+++ b/.all-contributorsrc
@@ -0,0 +1,62 @@
+{
+ "projectName": "next-saas-starter",
+ "projectOwner": "Blazity",
+ "repoType": "github",
+ "repoHost": "https://github.com",
+ "files": [
+ "README.md"
+ ],
+ "imageSize": 64,
+ "commit": true,
+ "commitConvention": "none",
+ "contributors": [
+ {
+ "login": "bmstefanski",
+ "name": "Bart Stefanski",
+ "avatar_url": "https://avatars.githubusercontent.com/u/28964599?v=4",
+ "profile": "https://bstefanski.com/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "ilasota",
+ "name": "Igor Lasota",
+ "avatar_url": "https://avatars.githubusercontent.com/u/34578189?v=4",
+ "profile": "https://github.com/ilasota",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "jbryn",
+ "name": "Jan Bryński",
+ "avatar_url": "https://avatars.githubusercontent.com/u/52970664?v=4",
+ "profile": "https://github.com/jbryn",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "logan-anderson",
+ "name": "Logan Anderson",
+ "avatar_url": "https://avatars.githubusercontent.com/u/43075109?v=4",
+ "profile": "https://www.logana.dev/",
+ "contributions": [
+ "code",
+ "doc",
+ "mentoring"
+ ]
+ },
+ {
+ "login": "fdukat",
+ "name": "Filip Dukat",
+ "avatar_url": "https://avatars.githubusercontent.com/u/87642690?v=4",
+ "profile": "https://github.com/fdukat",
+ "contributions": [
+ "doc"
+ ]
+ }
+ ],
+ "contributorsPerLine": 7
+}
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..bbce85a
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,5 @@
+SENDGRID_API_KEY=
+NEXT_PUBLIC_TINA_CLIENT_ID=
+NEXT_PUBLIC_EDIT_BRANCH="master"
+NEXT_PUBLIC_ORGANIZATION_NAME=
+NEXT_PUBLIC_USE_LOCAL_CLIENT=""
\ No newline at end of file
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..cad3818
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,40 @@
+{
+ "parser": "@typescript-eslint/parser",
+ "extends": ["react-app", "prettier", "plugin:react/recommended", "next/core-web-vitals"],
+ "env": {
+ "es6": true
+ },
+ "parserOptions": {
+ "sourceType": "module"
+ },
+ "rules": {
+ "react/prop-types": 0,
+ "react/react-in-jsx-scope": 0,
+ "react/display-name": 0,
+ "no-unused-vars": 0,
+ "sort-imports": ["error", { "ignoreCase": true, "ignoreDeclarationSort": true }],
+ "import/order": [
+ 1,
+ {
+ "groups": ["external", "builtin", "internal", "sibling", "parent", "index"],
+ "pathGroups": [
+ { "pattern": "env", "group": "internal" },
+ { "pattern": "types", "group": "internal" },
+ { "pattern": "components/**", "group": "internal" },
+ { "pattern": "contexts/**", "group": "internal" },
+ { "pattern": "hooks/**", "group": "internal" },
+ { "pattern": "pages/**", "group": "internal" },
+ { "pattern": "views/**", "group": "internal" },
+ { "pattern": "utils/**", "group": "internal" },
+ { "pattern": "public/**", "group": "internal", "position": "after" },
+ { "pattern": "posts/**", "group": "internal", "position": "after" }
+ ],
+ "pathGroupsExcludedImportTypes": ["internal"],
+ "alphabetize": {
+ "order": "asc",
+ "caseInsensitive": true
+ }
+ }
+ ]
+ }
+}
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..e1045be
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,11 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+ - package-ecosystem: "npm" # See documentation for possible values
+ directory: "/" # Location of package manifests
+ schedule:
+ interval: "weekly"
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 0000000..8ec3735
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,70 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches: [ master ]
+ schedule:
+ - cron: '29 1 * * 5'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'javascript' ]
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
+ # Learn more about CodeQL language support at https://git.io/codeql-language-support
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v2
+
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 https://git.io/JvXDl
+
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+ # and modify them (or add more) to build your code if your project
+ # uses a compiled language
+
+ #- run: |
+ # make bootstrap
+ # make release
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
diff --git a/.gitignore b/.gitignore
index 8f322f0..46e247a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,6 +25,7 @@ yarn-debug.log*
yarn-error.log*
# local env files
+<<<<<<< HEAD
.env*.local
# vercel
@@ -33,3 +34,12 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
+=======
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# vercel
+.vercel
+>>>>>>> temp-branch
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..6bfcf82
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,7 @@
+{
+ "printWidth": 140,
+ "tabWidth": 2,
+ "useTabs": false,
+ "singleQuote": true,
+ "trailingComma": "all"
+}
diff --git a/.tina/__generated__/.gitignore b/.tina/__generated__/.gitignore
new file mode 100644
index 0000000..5baa59d
--- /dev/null
+++ b/.tina/__generated__/.gitignore
@@ -0,0 +1 @@
+db
\ No newline at end of file
diff --git a/.tina/__generated__/_graphql.json b/.tina/__generated__/_graphql.json
new file mode 100644
index 0000000..f077007
--- /dev/null
+++ b/.tina/__generated__/_graphql.json
@@ -0,0 +1,1916 @@
+{
+ "kind": "Document",
+ "definitions": [
+ {
+ "kind": "ScalarTypeDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "Reference"
+ },
+ "description": {
+ "kind": "StringValue",
+ "value": "References another document, used as a foreign key"
+ },
+ "directives": []
+ },
+ {
+ "kind": "ScalarTypeDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "JSON"
+ },
+ "description": {
+ "kind": "StringValue",
+ "value": ""
+ },
+ "directives": []
+ },
+ {
+ "kind": "ObjectTypeDefinition",
+ "interfaces": [],
+ "directives": [],
+ "name": {
+ "kind": "Name",
+ "value": "SystemInfo"
+ },
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "filename"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "basename"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "breadcrumbs"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "excludeExtension"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Boolean"
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "ListType",
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "path"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "relativePath"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "extension"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "template"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "collection"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Collection"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "ObjectTypeDefinition",
+ "interfaces": [],
+ "directives": [],
+ "name": {
+ "kind": "Name",
+ "value": "PageInfo"
+ },
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "hasPreviousPage"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Boolean"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "hasNextPage"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Boolean"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "startCursor"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "endCursor"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "InterfaceTypeDefinition",
+ "description": {
+ "kind": "StringValue",
+ "value": ""
+ },
+ "name": {
+ "kind": "Name",
+ "value": "Node"
+ },
+ "interfaces": [],
+ "directives": [],
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "id"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "ID"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "InterfaceTypeDefinition",
+ "description": {
+ "kind": "StringValue",
+ "value": ""
+ },
+ "name": {
+ "kind": "Name",
+ "value": "Document"
+ },
+ "interfaces": [],
+ "directives": [],
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "sys"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "SystemInfo"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "id"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "ID"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "form"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "JSON"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "values"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "JSON"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "InterfaceTypeDefinition",
+ "description": {
+ "kind": "StringValue",
+ "value": "A relay-compliant pagination connection"
+ },
+ "name": {
+ "kind": "Name",
+ "value": "Connection"
+ },
+ "interfaces": [],
+ "directives": [],
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "totalCount"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Int"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "ObjectTypeDefinition",
+ "interfaces": [],
+ "directives": [],
+ "name": {
+ "kind": "Name",
+ "value": "Query"
+ },
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "getCollection"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "collection"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Collection"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "getCollections"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "ListType",
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Collection"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "node"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "id"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Node"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "getDocument"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "collection"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "relativePath"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentNode"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "getDocumentList"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "before"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "after"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "first"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Int"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "last"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Int"
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentConnection"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "getDocumentFields"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "JSON"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "getPostsDocument"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "relativePath"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PostsDocument"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "getPostsList"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "before"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "after"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "first"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Int"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "last"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Int"
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PostsConnection"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "ObjectTypeDefinition",
+ "interfaces": [],
+ "directives": [],
+ "name": {
+ "kind": "Name",
+ "value": "DocumentConnectionEdges"
+ },
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "cursor"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "node"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentNode"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "ObjectTypeDefinition",
+ "interfaces": [
+ {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Connection"
+ }
+ }
+ ],
+ "directives": [],
+ "name": {
+ "kind": "Name",
+ "value": "DocumentConnection"
+ },
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "pageInfo"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PageInfo"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "totalCount"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Int"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "edges"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "ListType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentConnectionEdges"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "ObjectTypeDefinition",
+ "interfaces": [],
+ "directives": [],
+ "name": {
+ "kind": "Name",
+ "value": "Collection"
+ },
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "name"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "slug"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "label"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "path"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "format"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "matches"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "templates"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "ListType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "JSON"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "fields"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "ListType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "JSON"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "documents"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "before"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "after"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "first"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Int"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "last"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Int"
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentConnection"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "UnionTypeDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentNode"
+ },
+ "directives": [],
+ "types": [
+ {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PostsDocument"
+ }
+ }
+ ]
+ },
+ {
+ "kind": "ObjectTypeDefinition",
+ "interfaces": [],
+ "directives": [],
+ "name": {
+ "kind": "Name",
+ "value": "Posts"
+ },
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "title"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "description"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "date"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "tags"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "imageUrl"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "body"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "JSON"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "ObjectTypeDefinition",
+ "interfaces": [
+ {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Node"
+ }
+ },
+ {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Document"
+ }
+ }
+ ],
+ "directives": [],
+ "name": {
+ "kind": "Name",
+ "value": "PostsDocument"
+ },
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "id"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "ID"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "sys"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "SystemInfo"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "data"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Posts"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "form"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "JSON"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "values"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "JSON"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "dataJSON"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "JSON"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "ObjectTypeDefinition",
+ "interfaces": [],
+ "directives": [],
+ "name": {
+ "kind": "Name",
+ "value": "PostsConnectionEdges"
+ },
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "cursor"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "node"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PostsDocument"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "ObjectTypeDefinition",
+ "interfaces": [
+ {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Connection"
+ }
+ }
+ ],
+ "directives": [],
+ "name": {
+ "kind": "Name",
+ "value": "PostsConnection"
+ },
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "pageInfo"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PageInfo"
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "totalCount"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "Int"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "edges"
+ },
+ "arguments": [],
+ "type": {
+ "kind": "ListType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PostsConnectionEdges"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "ObjectTypeDefinition",
+ "interfaces": [],
+ "directives": [],
+ "name": {
+ "kind": "Name",
+ "value": "Mutation"
+ },
+ "fields": [
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "addPendingDocument"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "collection"
+ },
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "relativePath"
+ },
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "template"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentNode"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "updateDocument"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "collection"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "relativePath"
+ },
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "params"
+ },
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentMutation"
+ }
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentNode"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "createDocument"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "collection"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "relativePath"
+ },
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "params"
+ },
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentMutation"
+ }
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentNode"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "updatePostsDocument"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "relativePath"
+ },
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "params"
+ },
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PostsMutation"
+ }
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PostsDocument"
+ }
+ }
+ }
+ },
+ {
+ "kind": "FieldDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "createPostsDocument"
+ },
+ "arguments": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "relativePath"
+ },
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "params"
+ },
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PostsMutation"
+ }
+ }
+ }
+ }
+ ],
+ "type": {
+ "kind": "NonNullType",
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PostsDocument"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "InputObjectTypeDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "DocumentMutation"
+ },
+ "fields": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "posts"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "PostsMutation"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "kind": "InputObjectTypeDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "PostsMutation"
+ },
+ "fields": [
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "title"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "description"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "date"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "tags"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "imageUrl"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "String"
+ }
+ }
+ },
+ {
+ "kind": "InputValueDefinition",
+ "name": {
+ "kind": "Name",
+ "value": "body"
+ },
+ "type": {
+ "kind": "NamedType",
+ "name": {
+ "kind": "Name",
+ "value": "JSON"
+ }
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.tina/__generated__/_lookup.json b/.tina/__generated__/_lookup.json
new file mode 100644
index 0000000..53ab149
--- /dev/null
+++ b/.tina/__generated__/_lookup.json
@@ -0,0 +1,31 @@
+{
+ "DocumentConnection": {
+ "type": "DocumentConnection",
+ "resolveType": "multiCollectionDocumentList",
+ "collections": [
+ "posts"
+ ]
+ },
+ "Node": {
+ "type": "Node",
+ "resolveType": "nodeDocument"
+ },
+ "DocumentNode": {
+ "type": "DocumentNode",
+ "resolveType": "multiCollectionDocument",
+ "createDocument": "create",
+ "updateDocument": "update"
+ },
+ "PostsDocument": {
+ "type": "PostsDocument",
+ "resolveType": "collectionDocument",
+ "collection": "posts",
+ "createPostsDocument": "create",
+ "updatePostsDocument": "update"
+ },
+ "PostsConnection": {
+ "type": "PostsConnection",
+ "resolveType": "collectionDocumentList",
+ "collection": "posts"
+ }
+}
\ No newline at end of file
diff --git a/.tina/__generated__/_schema.json b/.tina/__generated__/_schema.json
new file mode 100644
index 0000000..a295513
--- /dev/null
+++ b/.tina/__generated__/_schema.json
@@ -0,0 +1,276 @@
+{
+ "version": {
+ "fullVersion": "0.59.3",
+ "major": "0",
+ "minor": "59",
+ "patch": "3"
+ },
+ "meta": {},
+ "collections": [
+ {
+ "label": "Blog Posts",
+ "name": "posts",
+ "path": "posts",
+ "fields": [
+ {
+ "type": "string",
+ "label": "Title",
+ "name": "title",
+ "namespace": [
+ "posts",
+ "title"
+ ]
+ },
+ {
+ "type": "string",
+ "label": "Description",
+ "name": "description",
+ "namespace": [
+ "posts",
+ "description"
+ ]
+ },
+ {
+ "type": "string",
+ "label": "Date",
+ "name": "date",
+ "namespace": [
+ "posts",
+ "date"
+ ]
+ },
+ {
+ "type": "string",
+ "label": "Tags",
+ "name": "tags",
+ "namespace": [
+ "posts",
+ "tags"
+ ]
+ },
+ {
+ "type": "string",
+ "label": "Image URL",
+ "name": "imageUrl",
+ "namespace": [
+ "posts",
+ "imageUrl"
+ ]
+ },
+ {
+ "type": "rich-text",
+ "label": "Blog Post Body",
+ "name": "body",
+ "isBody": true,
+ "templates": [
+ {
+ "name": "Quote",
+ "label": "Quote",
+ "fields": [
+ {
+ "type": "string",
+ "name": "content",
+ "label": "Content",
+ "namespace": [
+ "posts",
+ "body",
+ "Quote",
+ "content"
+ ]
+ },
+ {
+ "type": "string",
+ "name": "author",
+ "label": "Author",
+ "namespace": [
+ "posts",
+ "body",
+ "Quote",
+ "author"
+ ]
+ },
+ {
+ "type": "string",
+ "name": "cite",
+ "label": "Cite",
+ "namespace": [
+ "posts",
+ "body",
+ "Quote",
+ "cite"
+ ]
+ }
+ ],
+ "namespace": [
+ "posts",
+ "body",
+ "Quote"
+ ]
+ },
+ {
+ "name": "ArticleImage",
+ "label": "ArticleImage",
+ "fields": [
+ {
+ "type": "string",
+ "name": "src",
+ "label": "Src",
+ "namespace": [
+ "posts",
+ "body",
+ "ArticleImage",
+ "src"
+ ]
+ },
+ {
+ "type": "string",
+ "name": "caption",
+ "label": "Caption",
+ "namespace": [
+ "posts",
+ "body",
+ "ArticleImage",
+ "caption"
+ ]
+ }
+ ],
+ "namespace": [
+ "posts",
+ "body",
+ "ArticleImage"
+ ]
+ },
+ {
+ "name": "Code",
+ "label": "Code",
+ "fields": [
+ {
+ "type": "string",
+ "name": "code",
+ "label": "Code",
+ "namespace": [
+ "posts",
+ "body",
+ "Code",
+ "code"
+ ]
+ },
+ {
+ "type": "string",
+ "name": "language",
+ "label": "Language",
+ "namespace": [
+ "posts",
+ "body",
+ "Code",
+ "language"
+ ]
+ },
+ {
+ "type": "string",
+ "name": "selectedLines",
+ "label": "Selected Lines",
+ "namespace": [
+ "posts",
+ "body",
+ "Code",
+ "selectedLines"
+ ]
+ },
+ {
+ "type": "boolean",
+ "name": "withCopyButton",
+ "label": "With Copy Button",
+ "namespace": [
+ "posts",
+ "body",
+ "Code",
+ "withCopyButton"
+ ]
+ },
+ {
+ "type": "boolean",
+ "name": "withLineNumbers",
+ "label": "With Line Numbers",
+ "namespace": [
+ "posts",
+ "body",
+ "Code",
+ "withLineNumbers"
+ ]
+ },
+ {
+ "type": "string",
+ "name": "caption",
+ "label": "Caption",
+ "namespace": [
+ "posts",
+ "body",
+ "Code",
+ "caption"
+ ]
+ }
+ ],
+ "namespace": [
+ "posts",
+ "body",
+ "Code"
+ ]
+ },
+ {
+ "name": "h2",
+ "label": "H2",
+ "inline": true,
+ "fields": [],
+ "namespace": [
+ "posts",
+ "body",
+ "h2"
+ ]
+ },
+ {
+ "name": "h3",
+ "label": "H3",
+ "inline": true,
+ "fields": [],
+ "namespace": [
+ "posts",
+ "body",
+ "h3"
+ ]
+ },
+ {
+ "name": "br",
+ "label": "BR",
+ "inline": true,
+ "fields": [],
+ "namespace": [
+ "posts",
+ "body",
+ "br"
+ ]
+ },
+ {
+ "name": "p",
+ "label": "P",
+ "inline": true,
+ "fields": [],
+ "namespace": [
+ "posts",
+ "body",
+ "p"
+ ]
+ }
+ ],
+ "namespace": [
+ "posts",
+ "body"
+ ]
+ }
+ ],
+ "namespace": [
+ "posts"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.tina/__generated__/frags.gql b/.tina/__generated__/frags.gql
new file mode 100644
index 0000000..595ff50
--- /dev/null
+++ b/.tina/__generated__/frags.gql
@@ -0,0 +1,8 @@
+fragment PostsParts on Posts {
+ title
+ description
+ date
+ tags
+ imageUrl
+ body
+}
diff --git a/.tina/__generated__/queries.gql b/.tina/__generated__/queries.gql
new file mode 100644
index 0000000..949e404
--- /dev/null
+++ b/.tina/__generated__/queries.gql
@@ -0,0 +1,38 @@
+query getPostsDocument($relativePath: String!) {
+ getPostsDocument(relativePath: $relativePath) {
+ sys {
+ filename
+ basename
+ breadcrumbs
+ path
+ relativePath
+ extension
+ }
+ id
+ data {
+ ...PostsParts
+ }
+ }
+}
+
+query getPostsList {
+ getPostsList {
+ totalCount
+ edges {
+ node {
+ id
+ sys {
+ filename
+ basename
+ breadcrumbs
+ path
+ relativePath
+ extension
+ }
+ data {
+ ...PostsParts
+ }
+ }
+ }
+ }
+}
diff --git a/.tina/__generated__/schema.gql b/.tina/__generated__/schema.gql
new file mode 100644
index 0000000..c7b1d63
--- /dev/null
+++ b/.tina/__generated__/schema.gql
@@ -0,0 +1,134 @@
+# DO NOT MODIFY THIS FILE. This file is automatically generated by Tina
+"""References another document, used as a foreign key"""
+scalar Reference
+
+""""""
+scalar JSON
+
+type SystemInfo {
+ filename: String!
+ basename: String!
+ breadcrumbs(excludeExtension: Boolean): [String!]!
+ path: String!
+ relativePath: String!
+ extension: String!
+ template: String!
+ collection: Collection!
+}
+
+type PageInfo {
+ hasPreviousPage: Boolean!
+ hasNextPage: Boolean!
+ startCursor: String!
+ endCursor: String!
+}
+
+""""""
+interface Node {
+ id: ID!
+}
+
+""""""
+interface Document {
+ sys: SystemInfo
+ id: ID!
+ form: JSON!
+ values: JSON!
+}
+
+"""A relay-compliant pagination connection"""
+interface Connection {
+ totalCount: Int!
+}
+
+type Query {
+ getCollection(collection: String): Collection!
+ getCollections: [Collection!]!
+ node(id: String): Node!
+ getDocument(collection: String, relativePath: String): DocumentNode!
+ getDocumentList(before: String, after: String, first: Int, last: Int): DocumentConnection!
+ getDocumentFields: JSON!
+ getPostsDocument(relativePath: String): PostsDocument!
+ getPostsList(before: String, after: String, first: Int, last: Int): PostsConnection!
+}
+
+type DocumentConnectionEdges {
+ cursor: String
+ node: DocumentNode
+}
+
+type DocumentConnection implements Connection {
+ pageInfo: PageInfo
+ totalCount: Int!
+ edges: [DocumentConnectionEdges]
+}
+
+type Collection {
+ name: String!
+ slug: String!
+ label: String
+ path: String!
+ format: String
+ matches: String
+ templates: [JSON]
+ fields: [JSON]
+ documents(before: String, after: String, first: Int, last: Int): DocumentConnection!
+}
+
+union DocumentNode = PostsDocument
+
+type Posts {
+ title: String
+ description: String
+ date: String
+ tags: String
+ imageUrl: String
+ body: JSON
+}
+
+type PostsDocument implements Node & Document {
+ id: ID!
+ sys: SystemInfo!
+ data: Posts!
+ form: JSON!
+ values: JSON!
+ dataJSON: JSON!
+}
+
+type PostsConnectionEdges {
+ cursor: String
+ node: PostsDocument
+}
+
+type PostsConnection implements Connection {
+ pageInfo: PageInfo
+ totalCount: Int!
+ edges: [PostsConnectionEdges]
+}
+
+type Mutation {
+ addPendingDocument(collection: String!, relativePath: String!, template: String): DocumentNode!
+ updateDocument(collection: String, relativePath: String!, params: DocumentMutation!): DocumentNode!
+ createDocument(collection: String, relativePath: String!, params: DocumentMutation!): DocumentNode!
+ updatePostsDocument(relativePath: String!, params: PostsMutation!): PostsDocument!
+ createPostsDocument(relativePath: String!, params: PostsMutation!): PostsDocument!
+}
+
+input DocumentMutation {
+ posts: PostsMutation
+}
+
+input PostsMutation {
+ title: String
+ description: String
+ date: String
+ tags: String
+ imageUrl: String
+ body: JSON
+}
+
+schema {
+ query: Query
+ mutation: Mutation
+}
+
\ No newline at end of file
diff --git a/.tina/__generated__/types.ts b/.tina/__generated__/types.ts
new file mode 100644
index 0000000..c2ff7e8
--- /dev/null
+++ b/.tina/__generated__/types.ts
@@ -0,0 +1,339 @@
+//@ts-nocheck
+// DO NOT MODIFY THIS FILE. This file is automatically generated by Tina
+import { gql } from 'tinacms';
+export type Maybe
+ Everything you need to build a great landing page / marketing website for your startup. Great SEO metrics, Green WebVitals, 🚀 Performance, Clean & Pragmatic Codebase out of the box.
+
+✨ Free Next.js marketing website template for SaaS startups ✨
+
+
+
+ View Demo
+ .
+ Report Bug
+ .
+ Request Feature
+
Created with :heart: at Blazity
+Blazity is a group of Next.js/Jamstack/Headless experts. Contact us at contact@blazity.com if you’d like to talk about your project or just to have a chat with us
+ + + + +Bart Stefanski 💻 |
+ Igor Lasota 💻 |
+ Jan Bryński 💻 |
+ Logan Anderson 💻 📖 🧑🏫 |
+
+ {tokens.map((line, i) => { + const lineNumber = i + 1; + const isSelected = selectedLines.includes(lineNumber); + const lineProps = getLineProps({ line, key: i }); + const className = lineProps.className + (isSelected ? ' selected-line' : ''); + + return ( +++ {withLineNumbers && + ); + })} +{lineNumber} } ++ {line.map((token, key) => ( + + ))} + +
Mail successfully sent!
+{content}+
${description}
+Sent from: ${referer || 'Not specified or hidden'}`,
+ };
+
+ try {
+ await sgMail.send(content);
+ res.status(204).end();
+ } catch (error) {
+ console.log('ERROR', error);
+ res.status(400).send({ message: error });
+ }
+}
diff --git a/pages/blog/[slug].tsx b/pages/blog/[slug].tsx
new file mode 100644
index 0000000..dc0b015
--- /dev/null
+++ b/pages/blog/[slug].tsx
@@ -0,0 +1,155 @@
+import { GetStaticPropsContext, InferGetStaticPropsType } from 'next';
+import Head from 'next/head';
+import React, { useEffect, useRef, useState } from 'react';
+import styled from 'styled-components';
+import { staticRequest } from 'tinacms';
+import Container from 'components/Container';
+import MDXRichText from 'components/MDXRichText';
+import { NonNullableChildrenDeep } from 'types';
+import { formatDate } from 'utils/formatDate';
+import { media } from 'utils/media';
+import { getReadTime } from 'utils/readTime';
+import Header from 'views/SingleArticlePage/Header';
+import MetadataHead from 'views/SingleArticlePage/MetadataHead';
+import OpenGraphHead from 'views/SingleArticlePage/OpenGraphHead';
+import ShareWidget from 'views/SingleArticlePage/ShareWidget';
+import StructuredDataHead from 'views/SingleArticlePage/StructuredDataHead';
+import { Posts, PostsDocument, Query } from '.tina/__generated__/types';
+
+export default function SingleArticlePage(props: InferGetStaticPropsType
+ Deserunt culpa consequat non nostrud esse cillum pariatur velit consequat. Est fugiat voluptate deserunt sint culpa sint.
+ Laboris irure veniam quis ea voluptate. Nulla ad proident ex excepteur. Sunt sint ex laborum dolor quis magna aliquip qui amet
+ nulla. Laboris proident aute exercitation irure esse id eu occaecat ad ipsum est. Dolor cillum Lorem occaecat enim veniam
+ ullamco cupidatat qui dolore exercitation Lorem eu quis magna. Esse cillum aliqua et laborum eu dolore consectetur. Exercitation
+ id non quis ex qui in dolore est est proident. Laborum nisi commodo fugiat nulla et magna veniam aliquip. Aliqua duis non
+ nostrud ea velit incididunt. Laboris nostrud incididunt laborum enim eu dolor. Culpa anim sit sit ea. Labore laborum et aute ex
+ est est excepteur labore voluptate deserunt. Amet ea laboris ea culpa dolor laborum consequat aliquip reprehenderit voluptate
+ non laboris ipsum. Quis excepteur pariatur est enim duis consectetur nulla cupidatat ipsum dolor nisi ipsum. Dolore dolor
+ nostrud aute dolore. Excepteur reprehenderit aliquip amet pariatur excepteur. Aliqua commodo nulla dolor ex nisi duis
+ reprehenderit sint aliqua in minim. Lorem amet quis non veniam ut reprehenderit aliquip mollit do ullamco pariatur.
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas, quidem error incidunt a doloremque voluptatem porro inventore
+ voluptate quo deleniti animi laboriosam.{' '}
+ Possimus ullam velit rem itaque consectetur, in distinctio? Lorem ipsum, dolor sit amet
+ consectetur adipisicing elit. Soluta repellendus quia quos obcaecati nihil. Laudantium non accusantium, voluptate eum nesciunt
+ at suscipit quis est soluta?
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas, quidem error incidunt a doloremque voluptatem porro inventore{' '}
+ voluptate quo deleniti animi laboriosam. Possimus ullam velit rem itaque consectetur, in distinctio?
+
+ Deserunt culpa consequat non nostrud esse cillum pariatur velit consequat. Est fugiat voluptate deserunt sint culpa sint.
+ Laboris irure veniam quis ea voluptate. Nulla ad proident ex excepteur. Sunt sint ex laborum dolor quis magna aliquip qui amet
+ nulla. Laboris proident aute exercitation irure esse id eu occaecat ad ipsum est. Dolor cillum Lorem occaecat enim veniam
+ ullamco cupidatat qui dolore exercitation Lorem eu quis magna. Esse cillum aliqua et laborum eu dolore consectetur. Exercitation
+ id non quis ex qui in dolore est est proident. Laborum nisi commodo fugiat nulla et magna veniam aliquip. Aliqua duis non
+ nostrud ea velit incididunt. Laboris nostrud incididunt laborum enim eu dolor. Culpa anim sit sit ea. Labore laborum et aute ex
+ est est excepteur labore voluptate deserunt. Amet ea laboris ea culpa dolor laborum consequat aliquip reprehenderit voluptate
+ non laboris ipsum. Quis excepteur pariatur est enim duis consectetur nulla cupidatat ipsum dolor nisi ipsum. Dolore dolor
+ nostrud aute dolore. Excepteur reprehenderit aliquip amet pariatur excepteur. Aliqua commodo nulla dolor ex nisi duis
+ reprehenderit sint aliqua in minim. Lorem amet quis non veniam ut reprehenderit aliquip mollit do ullamco pariatur.
+
+ Email: support@myawesomesaas.com
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Quibusdam quidem ipsam ratione dicta quis cupiditate consequuntur laborum ducimus iusto velit. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quibusdam quidem ipsam ratione dicta quis cupiditate consequuntur laborum ducimus iusto velit. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quibusdam quidem ipsam ratione dicta quis cupiditate consequuntur laborum ducimus iusto velit.
+
+ Reprehenderit aliquip minim commodo magna occaecat dolore labore mollit mollit do esse deserunt. Aliquip eu reprehenderit aute{' '}
+
+
+
+
+
+
+
+
+ Column 1
+ Column 2
+ Column 3
+ Column 4
+
+
+ Dolor do culpa excepteur proident anim duis deserunt nulla dolor et tempor.
+ Eu enim qui ea nostrud minim.
+ Proident officia velit ut in est culpa non adipisicing excepteur exercitation aliqua.
+ Duis proident adipisicing magna aute sint adipisicing sit deserunt minim eu.
+
+
+ Nisi cillum culpa adipisicing cillum.
+ Proident nulla cillum aute occaecat mollit labore.
+ Non ex eiusmod tempor cupidatat consequat anim et veniam nisi sint fugiat pariatur irure.
+ Consectetur nisi culpa non ex ipsum deserunt magna est est magna.
+
+
+ Officia laboris anim voluptate incididunt mollit mollit.
+ Adipisicing est consectetur id esse nostrud culpa non exercitation cupidatat pariatur dolore amet.
+ Dolor ex est ad ut adipisicing irure nulla esse aliqua nisi ipsum id aliqua.
+ Proident anim consequat enim sit sint pariatur.
+
+
+ Sint anim sint deserunt in elit ad Lorem dolore tempor.
+ Consequat nostrud irure anim do ex dolor amet ea dolore incididunt esse et cupidatat.
+ Eu nostrud occaecat incididunt deserunt Lorem ad Lorem elit.
+ Id ullamco in ad adipisicing magna elit ea minim sunt esse adipisicing.
+
+
+ Ea adipisicing ut nulla aute dolore quis in reprehenderit qui ipsum Lorem magna.
+ Irure ex dolore consequat mollit Lorem nostrud velit irure.
+ Dolore minim ad esse occaecat.
+ Qui id tempor ut culpa.
+
+
+ Ea ut esse non dolor do cupidatat.
+ Deserunt pariatur minim nisi elit ipsum officia irure id culpa ipsum.
+ Ea cillum voluptate consectetur et reprehenderit mollit ut excepteur exercitation do fugiat duis qui.
+ Id laborum officia aliqua ut nulla mollit.
+
+
+ Laborum et et sint ad incididunt amet aliqua commodo esse proident.
+ Velit aute proident aliqua consequat minim laborum reprehenderit reprehenderit eiusmod amet in aute.
+ Adipisicing adipisicing consequat incididunt officia in eu minim non cupidatat nulla nostrud sint.
+ Excepteur minim ea ex commodo nisi aute nostrud cupidatat consectetur.
+
+
+ Anim elit aliquip elit mollit pariatur consectetur commodo.
+ Consequat cupidatat sit sit quis labore culpa in duis duis amet elit.
+ Laborum Lorem pariatur id adipisicing minim.
+ Deserunt Lorem do id ea aliquip sunt.
+
+
+ Laborum aute laborum elit adipisicing velit commodo occaecat amet laborum.
+ Dolor voluptate duis elit id.
+ Excepteur sunt duis id officia id reprehenderit enim exercitation dolor.
+ Et excepteur duis adipisicing laboris labore adipisicing id dolor adipisicing exercitation eu nisi.
+
+
+ Esse consequat commodo irure elit nostrud esse ut magna commodo ipsum.
+ Exercitation exercitation ipsum qui aute ad commodo exercitation aliquip nisi aute Lorem in nulla.
+ Sint cillum esse quis mollit fugiat incididunt officia adipisicing do sint eu.
+ Consectetur aute ad aliquip eu Lorem proident irure aliqua aliqua officia reprehenderit reprehenderit amet.
+
+
+ Est Lorem exercitation eiusmod sit et.
+ Quis aliqua irure dolor do reprehenderit non id excepteur voluptate eiusmod veniam nostrud et elit.
+ Minim id sit officia consectetur irure id deserunt excepteur eu.
+
+ Reprehenderit pariatur reprehenderit voluptate cillum minim tempor elit sint eiusmod ullamco id incididunt officia dolore.
+
+
+
+
+
+ Reprehenderit aliquip minim commodo magna occaecat dolore labore mollit mollit do esse deserunt. Aliquip eu reprehenderit aute{' '}
+
+
+
+
+
+
+
+
+ Column 1
+ Column 2
+ Column 3
+ Column 4
+
+
+ Dolor do culpa excepteur proident anim duis deserunt nulla dolor et tempor.
+ Eu enim qui ea nostrud minim.
+ Proident officia velit ut in est culpa non adipisicing excepteur exercitation aliqua.
+ Duis proident adipisicing magna aute sint adipisicing sit deserunt minim eu.
+
+
+ Nisi cillum culpa adipisicing cillum.
+ Proident nulla cillum aute occaecat mollit labore.
+ Non ex eiusmod tempor cupidatat consequat anim et veniam nisi sint fugiat pariatur irure.
+ Consectetur nisi culpa non ex ipsum deserunt magna est est magna.
+
+
+ Officia laboris anim voluptate incididunt mollit mollit.
+ Adipisicing est consectetur id esse nostrud culpa non exercitation cupidatat pariatur dolore amet.
+ Dolor ex est ad ut adipisicing irure nulla esse aliqua nisi ipsum id aliqua.
+ Proident anim consequat enim sit sint pariatur.
+
+
+ Sint anim sint deserunt in elit ad Lorem dolore tempor.
+ Consequat nostrud irure anim do ex dolor amet ea dolore incididunt esse et cupidatat.
+ Eu nostrud occaecat incididunt deserunt Lorem ad Lorem elit.
+ Id ullamco in ad adipisicing magna elit ea minim sunt esse adipisicing.
+
+
+ Ea adipisicing ut nulla aute dolore quis in reprehenderit qui ipsum Lorem magna.
+ Irure ex dolore consequat mollit Lorem nostrud velit irure.
+ Dolore minim ad esse occaecat.
+ Qui id tempor ut culpa.
+
+
+ Ea ut esse non dolor do cupidatat.
+ Deserunt pariatur minim nisi elit ipsum officia irure id culpa ipsum.
+ Ea cillum voluptate consectetur et reprehenderit mollit ut excepteur exercitation do fugiat duis qui.
+ Id laborum officia aliqua ut nulla mollit.
+
+
+ Laborum et et sint ad incididunt amet aliqua commodo esse proident.
+ Velit aute proident aliqua consequat minim laborum reprehenderit reprehenderit eiusmod amet in aute.
+ Adipisicing adipisicing consequat incididunt officia in eu minim non cupidatat nulla nostrud sint.
+ Excepteur minim ea ex commodo nisi aute nostrud cupidatat consectetur.
+
+
+ Anim elit aliquip elit mollit pariatur consectetur commodo.
+ Consequat cupidatat sit sit quis labore culpa in duis duis amet elit.
+ Laborum Lorem pariatur id adipisicing minim.
+ Deserunt Lorem do id ea aliquip sunt.
+
+
+ Laborum aute laborum elit adipisicing velit commodo occaecat amet laborum.
+ Dolor voluptate duis elit id.
+ Excepteur sunt duis id officia id reprehenderit enim exercitation dolor.
+ Et excepteur duis adipisicing laboris labore adipisicing id dolor adipisicing exercitation eu nisi.
+
+
+ Esse consequat commodo irure elit nostrud esse ut magna commodo ipsum.
+ Exercitation exercitation ipsum qui aute ad commodo exercitation aliquip nisi aute Lorem in nulla.
+ Sint cillum esse quis mollit fugiat incididunt officia adipisicing do sint eu.
+ Consectetur aute ad aliquip eu Lorem proident irure aliqua aliqua officia reprehenderit reprehenderit amet.
+
+
+ Est Lorem exercitation eiusmod sit et.
+ Quis aliqua irure dolor do reprehenderit non id excepteur voluptate eiusmod veniam nostrud et elit.
+ Minim id sit officia consectetur irure id deserunt excepteur eu.
+
+ Reprehenderit pariatur reprehenderit voluptate cillum minim tempor elit sint eiusmod ullamco id incididunt officia dolore.
+
+
+
+## HEDONIST ROOTS
+
+Until recently, the prevailing view assumed lorem ipsum was born as a nonsense text. “It's not Latin, though it looks like it, and it actually says nothing,” Before & After magazine [answered a curious reader](https://www.straightdope.com/columns/read/2290/what-does-the-filler-text-lorem-ipsum-mean/), “Its ‘words’ loosely approximate the frequency with which letters occur in English, which is why at a glance it looks pretty real.”
+
+As Cicero would put it, “Um, not so fast.”
+
+The placeholder text, beginning with the line “Lorem ipsum dolor sit amet, consectetur adipiscing elit”, looks like Latin because in its youth, centuries ago, it was Latin.
+
+Richard McClintock, a Latin scholar from Hampden-Sydney College, is credited with discovering the source behind the ubiquitous filler text. In seeing a sample of lorem ipsum, his interest was piqued by consectetur—a genuine, albeit rare, Latin word. Consulting a Latin dictionary led McClintock to a passage from De Finibus Bonorum et Malorum (“On the Extremes of Good and Evil”), a first-century B.C. text from the Roman philosopher Cicero.
+
+In particular, the garbled words of lorem ipsum bear an unmistakable resemblance to sections 1.10.32–33 of Cicero's work, with the most notable passage excerpted below:
+
+
+
+McClintock's eye for detail certainly helped narrow the whereabouts of lorem ipsum's origin, however, the “how and when” still remain something of a mystery, with competing theories and timelines.
+
+## Creation timelines for the standard lorem ipsum passage vary, with some citing the 15th century and others the 20th.
+
+So how did the classical Latin become so incoherent? According to McClintock, a 15th century typesetter likely scrambled part of Cicero's De Finibus in order to provide placeholder text to mockup various fonts for a type specimen book.
+
+* It's difficult to find examples of lorem ipsum in use before Letraset made it popular as a dummy text in the 1960s, although McClintock says he remembers coming across the lorem ipsum passage in a book of old metal type samples. So far he hasn't relocated where he once saw the passage, but the popularity of Cicero in the 15th century supports the theory that the filler text has been used for centuries.
+* And anyways, as Cecil Adams reasoned, “\[Do you really] think graphic arts supply houses were hiring classics scholars in the 1960s?” Perhaps. But it seems reasonable to imagine that there was a version in use far before the age of Letraset.
+
+McClintock wrote to Before & After to explain his discovery;
+
+
+
diff --git a/posts/test-article-4.mdx b/posts/test-article-4.mdx
new file mode 100644
index 0000000..23eb2c0
--- /dev/null
+++ b/posts/test-article-4.mdx
@@ -0,0 +1,70 @@
+---
+title: Officia culpa tempor eu dolore dolor esse ex incididunt ea ullamco mollit occaecat cupidatat irure. 4
+description: Aliquip fugiat nostrud nulla eu exercitation culpa officia irure dolor elit eu duis. Irure exercitation ex ad id anim fugiat mollit magna et. Proident magna exercitation amet irure est anim dolore. Sint reprehenderit ullamco aliquip dolor veniam exercitation excepteur ex cupidatat aute fugiat dolore minim. Labore reprehenderit duis nostrud eu dolore consequat sit tempor nisi irure elit dolore irure culpa. Duis ea do quis magna adipisicing laboris officia Lorem pariatur. Deserunt ex cillum incididunt id esse ipsum.
+date: '2021-07-31'
+tags: nextjs,next,something-else,idk
+imageUrl: '/posts/test-article/example-image-1.jpeg'
+---
+
+## HISTORY, PURPOSE AND USAGE
+
+Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs. The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De Finibus Bonorum et Malorum for use in a type specimen book. It usually begins with:
+
+
+
+## HEDONIST ROOTS
+
+Until recently, the prevailing view assumed lorem ipsum was born as a nonsense text. “It's not Latin, though it looks like it, and it actually says nothing,” Before & After magazine [answered a curious reader](https://www.straightdope.com/columns/read/2290/what-does-the-filler-text-lorem-ipsum-mean/), “Its ‘words’ loosely approximate the frequency with which letters occur in English, which is why at a glance it looks pretty real.”
+
+**As Cicero would put it, “Um, not so fast.”**
+
+The placeholder text, beginning with the line “Lorem ipsum dolor sit amet, consectetur adipiscing elit”, looks like Latin because in its youth, centuries ago, it was Latin.
+
+Richard McClintock, a Latin scholar from **Hampden-Sydney College**, is credited with discovering the source behind the ubiquitous filler text. In seeing a sample of lorem ipsum, his interest was piqued by consectetur—a genuine, albeit rare, Latin word. Consulting a Latin dictionary led McClintock to a passage from De Finibus Bonorum et Malorum (“On the Extremes of Good and Evil”), a first-century B.C. text from the Roman philosopher Cicero.
+
+In particular, the garbled words of lorem ipsum bear an unmistakable resemblance to sections `1.10.32–33` of Cicero's work, with the most notable passage excerpted below:
+
+
+
+McClintock's eye for detail certainly helped narrow the whereabouts of lorem ipsum's origin, however, the “how and when” still remain something of a mystery, with competing theories and timelines.
+
+## Creation timelines for the standard lorem ipsum passage vary, with some citing the 15th century and others the 20th.
+
+So how did the classical Latin become so incoherent? According to McClintock, a 15th century typesetter likely scrambled part of Cicero's De Finibus in order to provide placeholder text to mockup various fonts for a type specimen book.
+
+- It's difficult to find examples of lorem ipsum in use before Letraset made it popular as a dummy text in the 1960s, although McClintock says he remembers coming across the lorem ipsum passage in a book of old metal type samples. So far he hasn't relocated where he once saw the passage, but the popularity of Cicero in the 15th century supports the theory that the filler text has been used for centuries.
+- And anyways, as Cecil Adams reasoned, “[Do you really] think graphic arts supply houses were hiring classics scholars in the 1960s?” Perhaps. But it seems reasonable to imagine that there was a version in use far before the age of Letraset.
+
+McClintock wrote to Before & After to explain his discovery;
+
+
diff --git a/posts/test-article-5.mdx b/posts/test-article-5.mdx
new file mode 100644
index 0000000..f1a8a9e
--- /dev/null
+++ b/posts/test-article-5.mdx
@@ -0,0 +1,70 @@
+---
+title: Officia culpa tempor eu dolore dolor esse ex incididunt ea ullamco mollit occaecat cupidatat irure. 5
+description: Aliquip fugiat nostrud nulla eu exercitation culpa officia irure dolor elit eu duis. Irure exercitation ex ad id anim fugiat mollit magna et. Proident magna exercitation amet irure est anim dolore. Sint reprehenderit ullamco aliquip dolor veniam exercitation excepteur ex cupidatat aute fugiat dolore minim. Labore reprehenderit duis nostrud eu dolore consequat sit tempor nisi irure elit dolore irure culpa. Duis ea do quis magna adipisicing laboris officia Lorem pariatur. Deserunt ex cillum incididunt id esse ipsum.
+date: '2021-07-31'
+tags: nextjs,next,something-else,idk
+imageUrl: '/posts/test-article/example-image-1.jpeg'
+---
+
+## HISTORY, PURPOSE AND USAGE
+
+Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs. The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De Finibus Bonorum et Malorum for use in a type specimen book. It usually begins with:
+
+
+
+## HEDONIST ROOTS
+
+Until recently, the prevailing view assumed lorem ipsum was born as a nonsense text. “It's not Latin, though it looks like it, and it actually says nothing,” Before & After magazine [answered a curious reader](https://www.straightdope.com/columns/read/2290/what-does-the-filler-text-lorem-ipsum-mean/), “Its ‘words’ loosely approximate the frequency with which letters occur in English, which is why at a glance it looks pretty real.”
+
+**As Cicero would put it, “Um, not so fast.”**
+
+The placeholder text, beginning with the line “Lorem ipsum dolor sit amet, consectetur adipiscing elit”, looks like Latin because in its youth, centuries ago, it was Latin.
+
+Richard McClintock, a Latin scholar from **Hampden-Sydney College**, is credited with discovering the source behind the ubiquitous filler text. In seeing a sample of lorem ipsum, his interest was piqued by consectetur—a genuine, albeit rare, Latin word. Consulting a Latin dictionary led McClintock to a passage from De Finibus Bonorum et Malorum (“On the Extremes of Good and Evil”), a first-century B.C. text from the Roman philosopher Cicero.
+
+In particular, the garbled words of lorem ipsum bear an unmistakable resemblance to sections `1.10.32–33` of Cicero's work, with the most notable passage excerpted below:
+
+
+
+McClintock's eye for detail certainly helped narrow the whereabouts of lorem ipsum's origin, however, the “how and when” still remain something of a mystery, with competing theories and timelines.
+
+## Creation timelines for the standard lorem ipsum passage vary, with some citing the 15th century and others the 20th.
+
+So how did the classical Latin become so incoherent? According to McClintock, a 15th century typesetter likely scrambled part of Cicero's De Finibus in order to provide placeholder text to mockup various fonts for a type specimen book.
+
+- It's difficult to find examples of lorem ipsum in use before Letraset made it popular as a dummy text in the 1960s, although McClintock says he remembers coming across the lorem ipsum passage in a book of old metal type samples. So far he hasn't relocated where he once saw the passage, but the popularity of Cicero in the 15th century supports the theory that the filler text has been used for centuries.
+- And anyways, as Cecil Adams reasoned, “[Do you really] think graphic arts supply houses were hiring classics scholars in the 1960s?” Perhaps. But it seems reasonable to imagine that there was a version in use far before the age of Letraset.
+
+McClintock wrote to Before & After to explain his discovery;
+
+
diff --git a/posts/test-article-6.mdx b/posts/test-article-6.mdx
new file mode 100644
index 0000000..2def86d
--- /dev/null
+++ b/posts/test-article-6.mdx
@@ -0,0 +1,70 @@
+---
+title: Officia culpa tempor eu dolore dolor esse ex incididunt ea ullamco mollit occaecat cupidatat irure. 6
+description: Aliquip fugiat nostrud nulla eu exercitation culpa officia irure dolor elit eu duis. Irure exercitation ex ad id anim fugiat mollit magna et. Proident magna exercitation amet irure est anim dolore. Sint reprehenderit ullamco aliquip dolor veniam exercitation excepteur ex cupidatat aute fugiat dolore minim. Labore reprehenderit duis nostrud eu dolore consequat sit tempor nisi irure elit dolore irure culpa. Duis ea do quis magna adipisicing laboris officia Lorem pariatur. Deserunt ex cillum incididunt id esse ipsum.
+date: '2021-07-31'
+tags: nextjs,next,something-else,idk
+imageUrl: '/posts/test-article/example-image-1.jpeg'
+---
+
+## HISTORY, PURPOSE AND USAGE
+
+Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs. The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De Finibus Bonorum et Malorum for use in a type specimen book. It usually begins with:
+
+
+
+## HEDONIST ROOTS
+
+Until recently, the prevailing view assumed lorem ipsum was born as a nonsense text. “It's not Latin, though it looks like it, and it actually says nothing,” Before & After magazine [answered a curious reader](https://www.straightdope.com/columns/read/2290/what-does-the-filler-text-lorem-ipsum-mean/), “Its ‘words’ loosely approximate the frequency with which letters occur in English, which is why at a glance it looks pretty real.”
+
+**As Cicero would put it, “Um, not so fast.”**
+
+The placeholder text, beginning with the line “Lorem ipsum dolor sit amet, consectetur adipiscing elit”, looks like Latin because in its youth, centuries ago, it was Latin.
+
+Richard McClintock, a Latin scholar from **Hampden-Sydney College**, is credited with discovering the source behind the ubiquitous filler text. In seeing a sample of lorem ipsum, his interest was piqued by consectetur—a genuine, albeit rare, Latin word. Consulting a Latin dictionary led McClintock to a passage from De Finibus Bonorum et Malorum (“On the Extremes of Good and Evil”), a first-century B.C. text from the Roman philosopher Cicero.
+
+In particular, the garbled words of lorem ipsum bear an unmistakable resemblance to sections `1.10.32–33` of Cicero's work, with the most notable passage excerpted below:
+
+
+
+McClintock's eye for detail certainly helped narrow the whereabouts of lorem ipsum's origin, however, the “how and when” still remain something of a mystery, with competing theories and timelines.
+
+## Creation timelines for the standard lorem ipsum passage vary, with some citing the 15th century and others the 20th.
+
+So how did the classical Latin become so incoherent? According to McClintock, a 15th century typesetter likely scrambled part of Cicero's De Finibus in order to provide placeholder text to mockup various fonts for a type specimen book.
+
+- It's difficult to find examples of lorem ipsum in use before Letraset made it popular as a dummy text in the 1960s, although McClintock says he remembers coming across the lorem ipsum passage in a book of old metal type samples. So far he hasn't relocated where he once saw the passage, but the popularity of Cicero in the 15th century supports the theory that the filler text has been used for centuries.
+- And anyways, as Cecil Adams reasoned, “[Do you really] think graphic arts supply houses were hiring classics scholars in the 1960s?” Perhaps. But it seems reasonable to imagine that there was a version in use far before the age of Letraset.
+
+McClintock wrote to Before & After to explain his discovery;
+
+
diff --git a/posts/test-article.mdx b/posts/test-article.mdx
new file mode 100644
index 0000000..45667c2
--- /dev/null
+++ b/posts/test-article.mdx
@@ -0,0 +1,70 @@
+---
+title: Officia culpa tempor eu dolore dolor esse ex incididunt ea ullamco mollit occaecat cupidatat irure.
+description: Aliquip fugiat nostrud nulla eu exercitation culpa officia irure dolor elit eu duis. Irure exercitation ex ad id anim fugiat mollit magna et. Proident magna exercitation amet irure est anim dolore. Sint reprehenderit ullamco aliquip dolor veniam exercitation excepteur ex cupidatat aute fugiat dolore minim. Labore reprehenderit duis nostrud eu dolore consequat sit tempor nisi irure elit dolore irure culpa. Duis ea do quis magna adipisicing laboris officia Lorem pariatur. Deserunt ex cillum incididunt id esse ipsum.
+date: '2021-07-31'
+tags: nextjs,next,something-else,idk
+imageUrl: '/posts/test-article/example-image-1.jpeg'
+---
+
+## HISTORY, PURPOSE AND USAGE
+
+Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs. The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De Finibus Bonorum et Malorum for use in a type specimen book. It usually begins with:
+
+
+
+## HEDONIST ROOTS
+
+Until recently, the prevailing view assumed lorem ipsum was born as a nonsense text. “It's not Latin, though it looks like it, and it actually says nothing,” Before & After magazine [answered a curious reader](https://www.straightdope.com/columns/read/2290/what-does-the-filler-text-lorem-ipsum-mean/), “Its ‘words’ loosely approximate the frequency with which letters occur in English, which is why at a glance it looks pretty real.”
+
+**As Cicero would put it, “Um, not so fast.”**
+
+The placeholder text, beginning with the line “Lorem ipsum dolor sit amet, consectetur adipiscing elit”, looks like Latin because in its youth, centuries ago, it was Latin.
+
+Richard McClintock, a Latin scholar from **Hampden-Sydney College**, is credited with discovering the source behind the ubiquitous filler text. In seeing a sample of lorem ipsum, his interest was piqued by consectetur—a genuine, albeit rare, Latin word. Consulting a Latin dictionary led McClintock to a passage from De Finibus Bonorum et Malorum (“On the Extremes of Good and Evil”), a first-century B.C. text from the Roman philosopher Cicero.
+
+In particular, the garbled words of lorem ipsum bear an unmistakable resemblance to sections `1.10.32–33` of Cicero's work, with the most notable passage excerpted below:
+
+
+
+McClintock's eye for detail certainly helped narrow the whereabouts of lorem ipsum's origin, however, the “how and when” still remain something of a mystery, with competing theories and timelines.
+
+## Creation timelines for the standard lorem ipsum passage vary, with some citing the 15th century and others the 20th.
+
+So how did the classical Latin become so incoherent? According to McClintock, a 15th century typesetter likely scrambled part of Cicero's De Finibus in order to provide placeholder text to mockup various fonts for a type specimen book.
+
+- It's difficult to find examples of lorem ipsum in use before Letraset made it popular as a dummy text in the 1960s, although McClintock says he remembers coming across the lorem ipsum passage in a book of old metal type samples. So far he hasn't relocated where he once saw the passage, but the popularity of Cicero in the 15th century supports the theory that the filler text has been used for centuries.
+- And anyways, as Cecil Adams reasoned, “[Do you really] think graphic arts supply houses were hiring classics scholars in the 1960s?” Perhaps. But it seems reasonable to imagine that there was a version in use far before the age of Letraset.
+
+McClintock wrote to Before & After to explain his discovery;
+
+
diff --git a/public/demo-illustration-1.svg b/public/demo-illustration-1.svg
new file mode 100644
index 0000000..40c0494
--- /dev/null
+++ b/public/demo-illustration-1.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/demo-illustration-2.svg b/public/demo-illustration-2.svg
new file mode 100644
index 0000000..02e6cb3
--- /dev/null
+++ b/public/demo-illustration-2.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/demo-illustration-3.png b/public/demo-illustration-3.png
new file mode 100644
index 0000000..6310586
Binary files /dev/null and b/public/demo-illustration-3.png differ
diff --git a/public/demo-illustration-4.png b/public/demo-illustration-4.png
new file mode 100644
index 0000000..2c339dd
Binary files /dev/null and b/public/demo-illustration-4.png differ
diff --git a/public/demo-illustration-5.png b/public/demo-illustration-5.png
new file mode 100644
index 0000000..216827e
Binary files /dev/null and b/public/demo-illustration-5.png differ
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..718d6fe
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/grid-icons/asset-1.svg b/public/grid-icons/asset-1.svg
new file mode 100644
index 0000000..52e2765
--- /dev/null
+++ b/public/grid-icons/asset-1.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/grid-icons/asset-2.svg b/public/grid-icons/asset-2.svg
new file mode 100644
index 0000000..aeef6b8
--- /dev/null
+++ b/public/grid-icons/asset-2.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/grid-icons/asset-3.svg b/public/grid-icons/asset-3.svg
new file mode 100644
index 0000000..55dc9b0
--- /dev/null
+++ b/public/grid-icons/asset-3.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/grid-icons/asset-4.svg b/public/grid-icons/asset-4.svg
new file mode 100644
index 0000000..4640567
--- /dev/null
+++ b/public/grid-icons/asset-4.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/grid-icons/asset-5.svg b/public/grid-icons/asset-5.svg
new file mode 100644
index 0000000..a01ae9e
--- /dev/null
+++ b/public/grid-icons/asset-5.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/grid-icons/asset-6.svg b/public/grid-icons/asset-6.svg
new file mode 100644
index 0000000..f0c7def
--- /dev/null
+++ b/public/grid-icons/asset-6.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/grid-icons/asset-7.svg b/public/grid-icons/asset-7.svg
new file mode 100644
index 0000000..eae0119
--- /dev/null
+++ b/public/grid-icons/asset-7.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/grid-icons/asset-8.svg b/public/grid-icons/asset-8.svg
new file mode 100644
index 0000000..c70a31b
--- /dev/null
+++ b/public/grid-icons/asset-8.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/grid-icons/asset-9.svg b/public/grid-icons/asset-9.svg
new file mode 100644
index 0000000..6e2c018
--- /dev/null
+++ b/public/grid-icons/asset-9.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/partners/logoipsum-logo-1.svg b/public/partners/logoipsum-logo-1.svg
new file mode 100644
index 0000000..efd9485
--- /dev/null
+++ b/public/partners/logoipsum-logo-1.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/partners/logoipsum-logo-2.svg b/public/partners/logoipsum-logo-2.svg
new file mode 100644
index 0000000..e70c0a7
--- /dev/null
+++ b/public/partners/logoipsum-logo-2.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/partners/logoipsum-logo-3.svg b/public/partners/logoipsum-logo-3.svg
new file mode 100644
index 0000000..135c678
--- /dev/null
+++ b/public/partners/logoipsum-logo-3.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/partners/logoipsum-logo-4.svg b/public/partners/logoipsum-logo-4.svg
new file mode 100644
index 0000000..a333a70
--- /dev/null
+++ b/public/partners/logoipsum-logo-4.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/partners/logoipsum-logo-5.svg b/public/partners/logoipsum-logo-5.svg
new file mode 100644
index 0000000..4cae1bd
--- /dev/null
+++ b/public/partners/logoipsum-logo-5.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/partners/logoipsum-logo-6.svg b/public/partners/logoipsum-logo-6.svg
new file mode 100644
index 0000000..5da75cc
--- /dev/null
+++ b/public/partners/logoipsum-logo-6.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/partners/logoipsum-logo-7.svg b/public/partners/logoipsum-logo-7.svg
new file mode 100644
index 0000000..d307cca
--- /dev/null
+++ b/public/partners/logoipsum-logo-7.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/play-icon.svg b/public/play-icon.svg
new file mode 100644
index 0000000..97c0303
--- /dev/null
+++ b/public/play-icon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/posts/test-article/example-image-1.jpeg b/public/posts/test-article/example-image-1.jpeg
new file mode 100644
index 0000000..475050a
Binary files /dev/null and b/public/posts/test-article/example-image-1.jpeg differ
diff --git a/public/posts/test-article/example-image-2.png b/public/posts/test-article/example-image-2.png
new file mode 100644
index 0000000..d7f96d9
Binary files /dev/null and b/public/posts/test-article/example-image-2.png differ
diff --git a/public/prism-theme.css b/public/prism-theme.css
new file mode 100644
index 0000000..ab82b4e
--- /dev/null
+++ b/public/prism-theme.css
@@ -0,0 +1 @@
+code[class*=language-],pre[class*=language-]{font-family:'Fira Code',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.next-dark-theme code[class*=language-],.next-dark-theme pre[class*=language-]{color:#f8f8f2;background:0 0}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}.next-dark-theme .code-wrapper,.next-dark-theme :not(pre)>code[class*=language-],.next-dark-theme pre[class*=language-]{background:#2e3440}.next-dark-theme :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.next-dark-theme .token.cdata,.next-dark-theme .token.comment,.next-dark-theme .token.doctype,.next-dark-theme .token.prolog{color:#636f88}.next-dark-theme .token.punctuation{color:#81a1c1}.next-dark-theme .namespace{opacity:.7}.next-dark-theme .token.constant,.next-dark-theme .token.deleted,.next-dark-theme .token.property,.next-dark-theme .token.symbol,.next-dark-theme .token.tag{color:#81a1c1}.next-dark-theme .token.number{color:#b48ead}.next-dark-theme .token.boolean{color:#81a1c1}.next-dark-theme .token.attr-name,.next-dark-theme .token.builtin,.next-dark-theme .token.char,.next-dark-theme .token.selector,.next-dark-theme .token.string,.token.inserted{color:#a3be8c}.next-dark-theme .selected-line::after{background-color:rgba(99,111,136,.4);border-color:#81a1c1}.next-dark-theme .language-css .token.string,.next-dark-theme .style .token.string,.next-dark-theme .token.entity,.next-dark-theme .token.operator,.next-dark-theme .token.url,.next-dark-theme .token.variable{color:#81a1c1}.next-dark-theme .token.atrule,.next-dark-theme .token.attr-value,.next-dark-theme .token.class-name,.next-dark-theme .token.function{color:#88c0d0}.next-dark-theme .token.keyword{color:#81a1c1}.next-dark-theme .token.important,.next-dark-theme .token.regex{color:#ebcb8b}.next-dark-theme .token.bold,.next-dark-theme .token.important{font-weight:700}.next-dark-theme .token.italic{font-style:italic}.next-dark-theme .token.entity{cursor:help}pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}.next-light-theme .code-wrapper,.next-light-theme code[class*=language-],.next-light-theme pre[class*=language-]{background:#f5f7ff;color:#5e6687}.next-light-theme code[class*=language-] ::-moz-selection,.next-light-theme code[class*=language-]::-moz-selection,.next-light-theme pre[class*=language-] ::-moz-selection,.next-light-theme pre[class*=language-]::-moz-selection{text-shadow:none;background:#dfe2f1}.next-light-theme code[class*=language-] ::selection,.next-light-theme code[class*=language-]::selection,.next-light-theme pre[class*=language-] ::selection,.next-light-theme pre[class*=language-]::selection{text-shadow:none;background:#dfe2f1}.next-light-theme pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}.next-light-theme :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em}.next-light-theme .token.cdata,.next-light-theme .token.comment,.next-light-theme .token.doctype,.next-light-theme .token.prolog{color:#898ea4}.next-light-theme .token.punctuation{color:#5e6687}.next-light-theme .token.namespace{opacity:.7}.next-light-theme .token.boolean,.next-light-theme .token.number,.next-light-theme .token.operator{color:#c76b29}.next-light-theme .token.property{color:#c08b30}.next-light-theme .token.tag{color:#3d8fd1}.next-light-theme .token.string{color:#22a2c9}.next-light-theme .token.selector{color:#6679cc}.next-light-theme .selected-line::after{background-color:rgba(107,115,148,.1);border-color:#c08b30}.next-light-theme .token.attr-name{color:#c76b29}.next-light-theme .language-css .token.string,.next-light-theme .style .token.string,.next-light-theme .token.entity,.next-light-theme .token.url{color:#22a2c9}.next-light-theme .token.attr-value,.next-light-theme .token.control,.next-light-theme .token.directive,.next-light-theme .token.keyword,.next-light-theme .token.unit{color:#ac9739}.next-light-theme .token.atrule,.next-light-theme .token.regex,.next-light-theme .token.statement{color:#22a2c9}.next-light-theme .token.placeholder,.next-light-theme .token.variable{color:#3d8fd1}.next-light-theme .token.deleted{text-decoration:line-through}.next-light-theme .token.inserted{border-bottom:1px dotted #202746;text-decoration:none}.next-light-theme .token.italic{font-style:italic}.next-light-theme .token.bold,.next-light-theme .token.important{font-weight:700}.next-light-theme .token.important{color:#c94922}.next-light-theme .token.entity{cursor:help}.next-light-theme pre>code.highlight{outline:.4em solid #c94922;outline-offset:.4em}.next-light-theme .line-numbers .line-numbers-rows{border-right-color:#dfe2f1}.next-light-theme .line-numbers-rows>span:before{color:#979db4}.next-light-theme .line-highlight{background:rgba(107,115,148,.2);background:-webkit-linear-gradient(left,rgba(107,115,148,.2) 70%,rgba(107,115,148,0));background:linear-gradient(to right,rgba(107,115,148,.2) 70%,rgba(107,115,148,0))}.selected-line{cursor:text;position:relative;width:100%}.selected-line::after{position:absolute;pointer-events:none;content:'';top:0;left:0;width:calc(100% + 2em);height:100%;border-left:2px solid;margin:0 -1em}
\ No newline at end of file
diff --git a/public/testimonials/author-photo-1.jpeg b/public/testimonials/author-photo-1.jpeg
new file mode 100644
index 0000000..9358491
Binary files /dev/null and b/public/testimonials/author-photo-1.jpeg differ
diff --git a/public/testimonials/author-photo-2.jpeg b/public/testimonials/author-photo-2.jpeg
new file mode 100644
index 0000000..68b8bb4
Binary files /dev/null and b/public/testimonials/author-photo-2.jpeg differ
diff --git a/public/testimonials/author-photo-3.jpeg b/public/testimonials/author-photo-3.jpeg
new file mode 100644
index 0000000..1027c59
Binary files /dev/null and b/public/testimonials/author-photo-3.jpeg differ
diff --git a/public/testimonials/company-logo-1.svg b/public/testimonials/company-logo-1.svg
new file mode 100644
index 0000000..864df2e
--- /dev/null
+++ b/public/testimonials/company-logo-1.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/testimonials/company-logo-2.svg b/public/testimonials/company-logo-2.svg
new file mode 100644
index 0000000..5e377c0
--- /dev/null
+++ b/public/testimonials/company-logo-2.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/testimonials/company-logo-3.svg b/public/testimonials/company-logo-3.svg
new file mode 100644
index 0000000..b758a2e
--- /dev/null
+++ b/public/testimonials/company-logo-3.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/vercel.svg b/public/vercel.svg
new file mode 100644
index 0000000..fbf0e25
--- /dev/null
+++ b/public/vercel.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/renovate.json b/renovate.json
new file mode 100644
index 0000000..39a2b6e
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "extends": [
+ "config:base"
+ ]
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..8376a7f
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "baseUrl": ".",
+ "incremental": true
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+ "exclude": ["node_modules"]
+}
diff --git a/types.ts b/types.ts
new file mode 100644
index 0000000..6c25095
--- /dev/null
+++ b/types.ts
@@ -0,0 +1,21 @@
+export type SingleNavItem = { title: string; href: string; outlined?: boolean };
+
+export type NavItems = SingleNavItem[];
+
+export type SingleArticle = {
+ slug: string;
+ content: string;
+ meta: {
+ title: string;
+ description: string;
+ date: string;
+ tags: string;
+ imageUrl: string;
+ };
+};
+
+export type NonNullableChildren
Contact Info
+ {singleTab.title}
+