feat: content

This commit is contained in:
Andreas Thomas 2023-03-26 14:00:02 +02:00
parent 82464d8091
commit 16a4d5e66d
No known key found for this signature in database
28 changed files with 557 additions and 289 deletions

View File

@ -7,12 +7,12 @@ import rehypeAutolinkHeadings from "rehype-autolink-headings";
var computedFields = {
path: {
type: "string",
resolve: (doc) => `/${doc._raw.flattenedPath}`
resolve: (doc) => `/${doc._raw.flattenedPath}`,
},
slug: {
type: "string",
resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/")
}
resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/"),
},
};
var Project = defineDocumentType(() => ({
name: "Project",
@ -20,27 +20,27 @@ var Project = defineDocumentType(() => ({
contentType: "mdx",
fields: {
published: {
type: "boolean"
type: "boolean",
},
title: {
type: "string",
required: true
required: true,
},
description: {
type: "string",
required: true
required: true,
},
date: {
type: "date"
type: "date",
},
url: {
type: "string"
type: "string",
},
repository: {
type: "string"
}
type: "string",
},
computedFields
},
computedFields,
}));
var Page = defineDocumentType(() => ({
name: "Page",
@ -49,13 +49,13 @@ var Page = defineDocumentType(() => ({
fields: {
title: {
type: "string",
required: true
required: true,
},
description: {
type: "string"
}
type: "string",
},
computedFields
},
computedFields,
}));
var contentlayer_config_default = makeSource({
contentDirPath: "./content",
@ -78,24 +78,20 @@ var contentlayer_config_default = makeSource({
},
onVisitHighlightedWord(node) {
node.properties.className = ["word--highlighted"];
}
}
},
},
],
[
rehypeAutolinkHeadings,
{
properties: {
className: ["subheading-anchor"],
ariaLabel: "Link to section"
}
}
]
]
}
ariaLabel: "Link to section",
},
},
],
],
},
});
export {
Page,
Project,
contentlayer_config_default as default
};
export { Page, Project, contentlayer_config_default as default };
//# sourceMappingURL=compiled-contentlayer-config-AAEZAM7W.mjs.map

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

@ -1,19 +1,65 @@
// 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__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' }
import projects__upstashWebAnalyticsMdx from './projects__upstash-web-analytics.mdx.json' assert { type: 'json' }
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__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",
};
import projects__upstashWebAnalyticsMdx from "./projects__upstash-web-analytics.mdx.json" assert {
type: "json",
};
export const allProjects = [projects__accessMdx, projects__envshareMdx, projects__planetfallMdx, projects__qstashMdx, projects__terraformProviderVercelMdx, projects__upstashAuthAnalyticsMdx, projects__upstashCliMdx, projects__upstashCoreAnalyticsMdx, projects__upstashEdgeFlagsMdx, projects__upstashKafkaMdx, projects__upstashQstashSdkMdx, projects__upstashRatelimitMdx, projects__upstashReactUiMdx, projects__upstashRedisMdx, projects__upstashWebAnalyticsMdx]
export const allProjects = [
projects__accessMdx,
projects__envshareMdx,
projects__planetfallMdx,
projects__qstashMdx,
projects__terraformProviderVercelMdx,
projects__upstashAuthAnalyticsMdx,
projects__upstashCliMdx,
projects__upstashCoreAnalyticsMdx,
projects__upstashEdgeFlagsMdx,
projects__upstashKafkaMdx,
projects__upstashQstashSdkMdx,
projects__upstashRatelimitMdx,
projects__upstashReactUiMdx,
projects__upstashRedisMdx,
projects__upstashWebAnalyticsMdx,
];

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

View File

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

View File

@ -1,12 +1,12 @@
// NOTE This file is auto-generated by Contentlayer
export { isType } from 'contentlayer/client'
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.mjs'
import { allProjects } from './Project/_index.mjs'
import allPages from "./Page/_index.json" assert { type: "json" };
import allProjects from "./Project/_index.json" assert { type: "json" };
export { allPages, allProjects }
export { allPages, allProjects };
export const allDocuments = [...allPages, ...allProjects]
export const allDocuments = [...allPages, ...allProjects];

View File

@ -1,66 +1,69 @@
// NOTE This file is auto-generated by Contentlayer
import type { Markdown, MDX, ImageFieldData, IsoDateTimeString } from 'contentlayer/core'
import * as Local from 'contentlayer/source-files'
import type {
Markdown,
MDX,
ImageFieldData,
IsoDateTimeString,
} from "contentlayer/core";
import * as Local from "contentlayer/source-files";
export { isType } from 'contentlayer/client'
export { isType } from "contentlayer/client";
export type { Markdown, MDX, ImageFieldData, IsoDateTimeString }
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
_id: string;
_raw: Local.RawDocumentData;
type: "Page";
title: string;
description?: string | undefined;
/** MDX file body */
body: MDX
path: string
slug: string
}
body: MDX;
path: string;
slug: string;
};
export type Project = {
/** File path relative to `contentDirPath` */
_id: string
_raw: Local.RawDocumentData
type: 'Project'
published?: boolean | undefined
title: string
description: string
date?: IsoDateTimeString | undefined
url?: string | undefined
repository?: string | undefined
_id: string;
_raw: Local.RawDocumentData;
type: "Project";
published?: boolean | undefined;
title: string;
description: string;
date?: IsoDateTimeString | undefined;
url?: string | undefined;
repository?: string | undefined;
/** MDX file body */
body: MDX
path: string
slug: string
}
body: MDX;
path: string;
slug: string;
};
/** Nested types */
/** Helper types */
export type AllTypes = DocumentTypes | NestedTypes
export type AllTypeNames = DocumentTypeNames | NestedTypeNames
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 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
documentTypes: DocumentTypes;
documentTypeMap: DocumentTypeMap;
documentTypeNames: DocumentTypeNames;
nestedTypes: NestedTypes;
nestedTypeMap: NestedTypeMap;
nestedTypeNames: NestedTypeNames;
allTypeNames: AllTypeNames;
}
declare global {
@ -68,12 +71,8 @@ declare global {
}
export type DocumentTypeMap = {
Page: Page
Project: Project
}
export type NestedTypeMap = {
}
Page: Page;
Project: Project;
};
export type NestedTypeMap = {};

View File

@ -1,9 +1,8 @@
"use client";
import { ArrowLeft, Github, Twitter } from "lucide-react";
import Link from "next/link";
import React, { useEffect, useMemo, useRef, useState } from "react";
import React, { useEffect, useRef, useState } from "react";
import { usePathname } from "next/navigation";
import Balancer from "react-wrap-balancer";
type Props = {
project: {
@ -27,7 +26,7 @@ export const Header: React.FC<Props> = ({ project }) => {
}
if (project.url) {
links.push({
label: "Live",
label: "Website",
href: project.url,
});
}
@ -91,7 +90,7 @@ export const Header: React.FC<Props> = ({ project }) => {
<div className="mx-auto max-w-7xl px-6 lg:px-8 text-center flex flex-col items-center">
<div className="mx-auto max-w-2xl lg:mx-0">
<h1 className="text-4xl font-bold tracking-tight text-white sm:text-6xl">
<Balancer>{project.title}</Balancer>
{project.title}
</h1>
<p className="mt-6 text-lg leading-8 text-zinc-300">
{project.description}

View File

@ -33,7 +33,7 @@ export default async function PostPage({ params }: Props) {
<ReportView slug={project.slug} />
<main className="bg-zinc-50">
<article className="px-4 py-12 mx-auto prose prose-zinc">
<article className="px-4 py-12 mx-auto prose prose-zinc prose-quoteless">
<Mdx code={project.body.code} />
</article>
</main>

View File

@ -8,4 +8,109 @@ published: true
---
TODO:
Manage Upstash resources in your terminal or CI.
![](https://raw.githubusercontent.com/upstash/cli/main/img/banner.svg)
![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/upstash/cli)
[![Downloads/week](https://img.shields.io/npm/dw/lstr.svg)](https://npmjs.org/package/@upstash/cli)
# Installation
## npm
You can install upstash's cli directly from npm
```bash
npm i -g @upstash/cli
```
It will be added as `upstash` to your system's path.
## Compiled binaries:
`upstash` is also available from the
[releases page](https://github.com/upstash/upstash-cli/releases/latest) compiled
for windows, linux and mac (both intel and m1).
# Usage
```bash
> upstash
Usage: upstash
Version: development
Description:
Official cli for Upstash products
Options:
-h, --help - Show this help.
-V, --version - Show the version number for this program.
-c, --config <string> - Path to .upstash.json file
Commands:
auth - Login and logout
redis - Manage redis database instances
kafka - Manage kafka clusters and topics
team - Manage your teams and their members
Environment variables:
UPSTASH_EMAIL <string> - The email you use on upstash
UPSTASH_API_KEY <string> - The api key from upstash
```
## Authentication
When running `upstash` for the first time, you should log in using
`upstash auth login`. Provide your email and an api key.
[See here for how to get a key.](https://docs.upstash.com/redis/howto/developerapi#api-development)
As an alternative to logging in, you can provide `UPSTASH_EMAIL` and
`UPSTASH_API_KEY` as environment variables.
## Usage
Let's create a new redis database:
```
> upstash redis create --name=my-db --region=eu-west-1
Database has been created
database_id a3e25299-132a-45b9-b026-c73f5a807859
database_name my-db
database_type Pay as You Go
region eu-west-1
type paid
port 37090
creation_time 1652687630
state active
password 88ae6392a1084d1186a3da37fb5f5a30
user_email andreas@upstash.com
endpoint eu1-magnetic-lacewing-37090.upstash.io
edge false
multizone false
rest_token AZDiASQgYTNlMjUyOTktMTMyYS00NWI5LWIwMjYtYzczZjVhODA3ODU5ODhhZTYzOTJhMTA4NGQxMTg2YTNkYTM3ZmI1ZjVhMzA=
read_only_rest_token ApDiASQgYTNlMjUyOTktMTMyYS00NWI5LWIwMjYtYzczZjVhODA3ODU5O_InFjRVX1XHsaSjq1wSerFCugZ8t8O1aTfbF6Jhq1I=
You can visit your database details page: https://console.upstash.com/redis/a3e25299-132a-45b9-b026-c73f5a807859
Connect to your database with redis-cli: redis-cli -u redis://88ae6392a1084d1186a3da37fb5f5a30@eu1-magnetic-lacewing-37090.upstash.io:37090
```
## Output
Most commands support the `--json` flag to return the raw api response as json,
which you can parse and automate your system.
```bash
> upstash redis create --name=test2113 --region=us-central1 --json | jq '.endpoint'
"gusc1-clean-gelding-30208.upstash.io"
```

View File

@ -8,4 +8,93 @@ published: true
---
TODO:
This library offers some low level building blocks to record and analyze custom events in Redis.
It's main purpose is to provide a simple way to record and query events in Redis without having to worry about the underlying data structure so we can build more advanced analytics features on top of it.
## Quickstart
1. Create a redis database
Go to [console.upstash.com/redis](https://console.upstash.com/redis) and create
a new global database.
After creating the db, copy the `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` to your `.env` file.
3. Install `@upstash/analytics` in your project
```bash
npm install @upstash/analytics @upstash/redis
```
4. Create an analytics client
```ts
import { Analytyics } from "@upstash/analytics";
import { Redis } from "@upstash/redis";
const analytics = new Analytics({
redis: Redis.fromEnv(),
window: "1d",
});
```
5. Ingest some events
An event consists of a `time` field and any additional key-value pairs that you can use to record any information you want.
```ts
const event = {
time: Date.now() // optional (default: Date.now())
userId: "chronark",
page: "/auth/login",
country: "DE",
}
await analytics.ingest("pageviews", event);
```
4. Query your events
```ts
const result = await analytics.query("pageviews");
```
## Development
This project uses `pnpm` for dependency management.
#### Install dependencies
```bash
pnpm install
```
#### Build
```bash
pnpm build
```
## Database Schema
All metrics are stored in Redis `Hash` data types and sharded into buckets based on the `window` option.
```
@upstash/analytics:{TABLE}:{TIMESTAMP}
```
- `TABLE` is a namespace to group events together. ie for managing multiple projects int a single database
- `TIMESTAMP` is the starting timestamp of each window
The field of each hash is a serialized JSON object with the user's event data and the value is the number of times this event has been recorded.
```json
{
'{"page": "/auth/login","country": "DE"}': 5,
'{"page": "/auth/login","country": "US"}': 2
}
```

View File

@ -8,4 +8,22 @@ published: true
---
TODO:
Whether you want to ship without breaking things, run A/B tests or just want to test in production,
feature flags are a great way to dynamically change the behaviour of your app without redeploying. We're excited to announce the public
beta release of our new feature flagging library: [@upstash/edge-flags](https://github.com/upstash/edge-flags).
*Edge Flags*, as the name implies, is a feature flag solution built to run at the edge. It is using [Upstash Redis](https://upstash.com/), a globally replicated serverless Redis service, to store configuration and is
designed to work with [Next.js](https://nextjs.org) and [Vercel](https://vercel.com). We want to support other frameworks in the future, so if you have a suggestion, please let us know!
With the ability to toggle features on and off at the edge, you can quickly respond
to user feedback and optimize the user experience. Whether you are looking to
perform A/B testing, gradually roll out a new feature, or simply have the
ability to turn things off in case of an issue, our feature flagging library has
you covered.
## Reference
Check out the full announcement on [upstash.com](https://upstash.com/blog/edge-flags-beta) for more details.

View File

@ -7,4 +7,15 @@ repository: upstash/sdk-qstash-ts
published: true
---
TODO:
@upstash/qstash is the official client and consumer for [QStash](https://chronark.com/projects/qstash).
QStash is the message broker between your serverless apps. You send an HTTP
request to QStash, that includes a destination, a payload and optional settings.
We durably store your message and will deliver it to the destination API via
HTTP. In case the destination is not ready to receive the message, we will retry
the message later, to guarentee at-least-once delivery.
```bash
npm install @upstash/qstash
```

View File

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

View File

@ -8,4 +8,42 @@ published: true
---
TODO:
In today's digital age, serverless computing has become increasingly popular due to its scalability and cost-efficiency. One of the challenges of serverless computing is to manage resources efficiently, and one critical aspect of this is rate limiting. Rate limiting is a technique that limits the number of requests a client can make to a server over a given period. This technique can prevent abuse, improve performance, and reduce costs. One npm package that helps implement rate limiting for serverless applications is @upstash/ratelimit, built on top of Upstash Redis.
Upstash is a managed Redis-compatible database service designed for serverless applications.
`@upstash/ratelimit` is an npm package that provides serverless rate limiting using Upstash Redis. The package offers a simple API that can be used to limit the number of requests a client can make within a given time frame. The following algorithms are supported:
- Fixed window
- Sliding window
- Leaky bucket
Using `@upstash/ratelimit` is straightforward. First, you need to install the package using npm:
```bash
npm install @upstash/ratelimit @upstash/redis
```
Then, you can use it in your application:
```ts
import { Ratelimit } from "@upstash/ratelimit"
import { Redis } from "@upstash/redis"
const ratelimit = new Ratelimit({
redis: new Redis({
url: "",
token: ""
}),
limiter: Ratelimit.slidingWindow(10, "10s"),
analytics: true
})
// Check if the client has exceeded the rate limit
const { success } = await ratelimit.limit("identifier")
```
In the code above, we initialize Upstash with our Upstash Redis credentials and define our rate limiting rules. We then call the `limit` function, passing the identifier. The function returns a Promise that resolves with `success` and some other useful data.
`@upstash/ratelimit` is a useful npm package for serverless rate limiting that simplifies the process of implementing rate limiting for serverless applications. The package is built on top of Upstash Redis, which provides a complete solution for serverless applications. With `@upstash/ratelimit`, serverless developers can easily implement rate limiting, which can help prevent abuse, improve performance, and reduce costs.

View File

@ -8,4 +8,5 @@ published: true
---
TODO:
`@upstash/react-ui` is powering the CLI in your browser on [console.upstash.com](https://comsole.upstash.com). It allows you to interact with your Upstash Redis database in a simple and intuitive way.

View File

@ -8,47 +8,15 @@ published: true
---
Upstash is a cloud-based service provider that offers a Redis-compatible service. In addition to that, we have also created an npm package called `@upstash/redis`. This package provides a strongly typed Redis client that uses HTTP instead of TCP to communicate with the database, making it perfect for serverless and edge runtimes.
`@upstash/redis` is an HTTP/REST based Redis client for typescript, built on top
of [Upstash REST API](https://docs.upstash.com/features/restapi).
Redis is a popular open-source, in-memory data structure store that can be used as a database, cache, and message broker. It is commonly used for web applications that require fast data access and manipulation. Redis clients communicate with Redis servers using the Redis protocol over TCP/IP.
It is the only connectionless (HTTP based) Redis client and designed for:
However, in some cases, TCP is not available. For example, edge functions run on cloud platforms, which often block TCP connections for various reasons. This is where `@upstash/redis` comes in handy. Instead of using TCP, it uses HTTP to communicate with the servers.
- Serverless functions (AWS Lambda ...)
- Cloudflare Workers (see
[the example](https://github.com/upstash/upstash-redis/tree/main/examples/cloudflare-workers))
- Fastly Compute@Edge (see
[the example](https://github.com/upstash/upstash-redis/tree/main/examples/fastly))
- Next.js, Jamstack ...
- Client side web/mobile applications
- WebAssembly
- and other environments where HTTP is preferred over TCP.
The package is designed to be easy to use and provides a simple API for Redis commands. It also includes support for Redis transactions and Lua scripting. It is written in TypeScript, which provides static typing and better code completion in modern editors.
See
[the list of APIs](https://docs.upstash.com/features/restapi#rest---redis-api-compatibility)
supported.
## Quick Start
### Install
#### Node.js
```bash
npm install @upstash/redis
```
#### Deno
```ts
import { Redis } from "https://deno.land/x/upstash_redis/mod.ts";
```
### Create database
Create a new redis database on [upstash](https://console.upstash.com/)
## Basic Usage:
One of the main benefits of using `@upstash/redis` is that it is strongly typed. This means that you get better type checking and error handling in your code. Additionally, the package is designed to be lightweight and optimized for performance. This makes it an excellent choice for applications that require fast data access and manipulation.
```ts
import { Redis } from "@upstash/redis"
@ -74,14 +42,4 @@ console.log(data)
await redis.lpush('elements', 'magnesium')
data = await redis.lrange('elements', 0, 100 )
console.log(data)
// hash
await redis.hset('people', {name: 'joe'})
data = await redis.hget('people', 'name' )
console.log(data)
// sets
await redis.sadd('animals', 'cat')
data = await redis.spop('animals', 1)
console.log(data)
```

View File

@ -5,4 +5,4 @@ repository: upstash/web-analytics
published: true
---
TODO:
Coming soon

View File

@ -2,10 +2,22 @@ const defaultTheme = require("tailwindcss/defaultTheme");
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./app/**/*.{js,ts,jsx,tsx}", "./mdx-components.tsx"],
content: [
"./app/**/*.{js,ts,jsx,tsx}",
"./mdx-components.tsx",
"content/**/*.mdx",
],
theme: {
extend: {
typography: {
quoteless: {
css: {
"blockquote p:first-of-type::before": { content: "none" },
"blockquote p:first-of-type::after": { content: "none" },
},
},
},
fontFamily: {
sans: ["var(--font-inter)", ...defaultTheme.fontFamily.sans],
display: ["var(--font-grotesk)"],