Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions apps/engineering/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# deps
/node_modules

# generated content
.contentlayer
.content-collections
.source

# test & build
/coverage
/.next/
/out/
/build
*.tsbuildinfo

# misc
.DS_Store
*.pem
/.pnp
.pnp.js
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# others
.env*.local
.vercel
next-env.d.ts
27 changes: 26 additions & 1 deletion apps/engineering/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,26 @@
# Unkey Docs
# engineering

This is a Next.js application generated with
[Create Fumadocs](https://github.com/fuma-nama/fumadocs).

Run development server:

```bash
npm run dev
# or
pnpm dev
# or
yarn dev
```

Open http://localhost:3000 with your browser to see the result.

## Learn More

To learn more about Next.js and Fumadocs, take a look at the following
resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js
features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
- [Fumadocs](https://fumadocs.vercel.app) - learn about Fumadocs
11 changes: 11 additions & 0 deletions apps/engineering/app/(home)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { HomeLayout } from "fumadocs-ui/home-layout";
import type { ReactNode } from "react";
import { baseOptions } from "../layout.config";

export default function Layout({
children,
}: {
children: ReactNode;
}): React.ReactElement {
return <HomeLayout {...baseOptions}>{children}</HomeLayout>;
}
16 changes: 16 additions & 0 deletions apps/engineering/app/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Link from "next/link";

export default function HomePage() {
return (
<main className="flex h-screen flex-col justify-center text-center">
<h1 className="mb-4 text-2xl font-bold">Unkey Engineering</h1>
<p className="text-fd-muted-foreground">
You can open{" "}
<Link href="/docs" className="text-fd-foreground font-semibold underline">
/docs
</Link>{" "}
and see the documentation.{" "}
</p>
</main>
);
}
12 changes: 12 additions & 0 deletions apps/engineering/app/api/search/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { source } from "@/app/source";
import { createSearchAPI } from "fumadocs-core/search/server";

export const { GET } = createSearchAPI("advanced", {
indexes: source.getPages().map((page) => ({
title: page.data.title,
description: page.data.description,
structuredData: page.data.structuredData,
id: page.url,
url: page.url,
})),
});
44 changes: 44 additions & 0 deletions apps/engineering/app/docs/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { source } from "@/app/source";
import defaultMdxComponents from "fumadocs-ui/mdx";
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from "fumadocs-ui/page";
import type { Metadata } from "next";
import { notFound } from "next/navigation";

export default async function Page({
params,
}: {
params: { slug?: string[] };
}) {
const page = source.getPage(params.slug);
if (!page) {
notFound();
}
Comment on lines +12 to +15
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Missing 'await' when calling asynchronous 'source.getPage'

If source.getPage is an asynchronous function, you should use await to ensure the function resolves before proceeding:

- const page = source.getPage(params.slug);
+ const page = await source.getPage(params.slug);

Committable suggestion was skipped due to low confidence.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chronark, glad it makes sense!

(_/)
(• ᴗ •)
/


const MDX = page.data.body;

return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription>{page.data.description}</DocsDescription>
<DocsBody>
<MDX components={{ ...defaultMdxComponents }} />
</DocsBody>
</DocsPage>
);
}

export async function generateStaticParams() {
return source.generateParams();
}

export function generateMetadata({ params }: { params: { slug?: string[] } }) {
const page = source.getPage(params.slug);
if (!page) {
notFound();
}

return {
title: page.data.title,
description: page.data.description,
} satisfies Metadata;
}
49 changes: 49 additions & 0 deletions apps/engineering/app/docs/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { source } from "@/app/source";
import { RootToggle } from "fumadocs-ui/components/layout/root-toggle";
import { DocsLayout } from "fumadocs-ui/layout";
import { Code, Component, Handshake, Terminal } from "lucide-react";
import type { ReactNode } from "react";
import { baseOptions } from "../layout.config";

export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout
tree={source.pageTree}
{...baseOptions}
sidebar={{
banner: (
<RootToggle
options={[
{
title: "Contributing",
description: "Create your first PR",
url: "/docs/contributing",
icon: <Code className="size-4 text-blue-600 dark:text-blue-400" />,
},
{
title: "Company",
description: "How we work",
url: "/docs/company",
icon: <Handshake className="size-4 text-amber-600 dark:text-amber-400" />,
},
{
title: "API Design",
description: "Look and feel",
url: "/docs/api-design",
icon: <Terminal className="size-4 text-emerald-600 dark:text-emerald-400" />,
},
{
title: "Architecture",
description: "How does Unkey work",
url: "/docs/architecture",
icon: <Component className="size-4 text-purple-600 dark:text-purple-400" />,
},
]}
/>
),
}}
>
{children}
</DocsLayout>
);
}
3 changes: 3 additions & 0 deletions apps/engineering/app/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
26 changes: 26 additions & 0 deletions apps/engineering/app/layout.config.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { HomeLayoutProps } from "fumadocs-ui/home-layout";

/**
* Shared layout configurations
*
* you can configure layouts individually from:
* Home Layout: app/(home)/layout.tsx
* Docs Layout: app/docs/layout.tsx
*/
export const baseOptions: HomeLayoutProps = {
nav: {
title: "Unkey Engineering",
},
githubUrl: "https://github.com/unkeyed/unkey",
links: [
{
text: "Documentation",
url: "/docs",
active: "nested-url",
},
{
text: "GitHub",
url: "https://github.com/unkeyed/unkey",
},
],
};
22 changes: 22 additions & 0 deletions apps/engineering/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Banner } from "fumadocs-ui/components/banner";
import { RootProvider } from "fumadocs-ui/provider";
import { Inter } from "next/font/google";
import type { ReactNode } from "react";
import "./global.css";

const inter = Inter({
subsets: ["latin"],
});

export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={inter.className} suppressHydrationWarning>
<body>
<RootProvider>
<Banner variant="rainbow">The new place for our engineering docs</Banner>
{children}
</RootProvider>
</body>
</html>
);
}
8 changes: 8 additions & 0 deletions apps/engineering/app/source.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { docs, meta } from "@/.source";
import { loader } from "fumadocs-core/source";
import { createMDXSource } from "fumadocs-mdx";

export const source = loader({
baseUrl: "/docs",
source: createMDXSource(docs, meta),
});
31 changes: 31 additions & 0 deletions apps/engineering/content/docs/api-design/errors.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
title: Errors
description: 'Error handling for Unkey APIs'
---


Machine and human readable error codes

The Unkey API returns machine readable error codes to quickly identify the type of error as well as link to the docs and a requestId. Please always include the requestId in your error report.

```json
{
"error": {
"code": "UNAUTHORIZED",
"message": "We were unable to authorize your request. Either your key was missing, malformed or does not have the required permissions.",
"docs": "https://unkey.api/docs/api-reference/errors/code/UNAUTHORIZED",
"requestId": "req_1234567890"
}
}
```

If you can’t debug something on your own or think there is a bug, please get in touch with us on Discord or Email and provide the full error response.


## In the future

When we move the API from cloudflare to stateful servers, we will expand upon this
to offer more error details to the user in a well defined format.


[RFC9457](https://www.rfc-editor.org/rfc/rfc9457.html) looks interesting.
17 changes: 17 additions & 0 deletions apps/engineering/content/docs/api-design/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: Introduction
description: How should our API look and feel.
---

Most of our users interact more with our API than with our dashboard. Therefore we need to carefully design the experience they will have.




## Goals for a great developer experience

- must be intuitive and predictable across programming languages.
- must be helpful when things go wrong
- never leave the user alone without a clear action to resolve their issue
- must have excellent documentation.
- must be fast.
3 changes: 3 additions & 0 deletions apps/engineering/content/docs/api-design/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"pages": ["rpc", "errors"]
}
36 changes: 36 additions & 0 deletions apps/engineering/content/docs/api-design/rpc.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: RPC style
description: Naming and method conventions
---

The Unkey API uses HTTP RPC-style methods and generally follow the schema:

```bash
https://api.unkey.dev/{version}/{service}.{procedure}
```
For example `GET https://api.unkey.dev/v1/apis.listKeys` to list all keys for an API.

## HTTP Methods
We strictly use only `GET` and `POST` methods. `PUT` and `DELETE` are not used.


### GET
The `GET` methods is used for reading data. Filtering, sorting, or pagination is done via query parameters.

```
curl "https://api.unkey.dev/v1/keys.getKey?keyId=key_123" \
-H "Authorization: Bearer <ROOT_KEY>"
```


### POST
The `POST` method is used for creating, updating, and deleting data. Data is passed as `application/json` in the request body.


```
curl -XPOST "https://api.unkey.dev/v1/keys.createKey" \
-H "Authorization: Bearer <ROOT_KEY>" \
-H "Content-Type: application/json" \
-d '{ "apiId": "api_123", "name": "My Key" }'
```

6 changes: 6 additions & 0 deletions apps/engineering/content/docs/architecture/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Overview
---


Hello
3 changes: 3 additions & 0 deletions apps/engineering/content/docs/architecture/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"pages": ["index"]
}
13 changes: 13 additions & 0 deletions apps/engineering/content/docs/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: Hello World
description: Your first document
---

Welcome to the docs! You can start writing documents in `/content/docs`.

## What is Next?

<Cards>
<Card title="Learn more about Next.js" href="https://nextjs.org/docs" />
<Card title="Learn more about Fumadocs" href="https://fumadocs.vercel.app" />
</Cards>
3 changes: 3 additions & 0 deletions apps/engineering/content/docs/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"pages": ["contributing", "api-design", "mdx", "cli"]
}
7 changes: 7 additions & 0 deletions apps/engineering/content/docs/services/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"title": "Fumadocs Core",
"description": "The headless library",
"icon": "Library",
"root": true,
"pages": []
}
Loading