docs: move documentation into monorepo

This commit is contained in:
lfleischmann
2022-09-12 13:15:42 +02:00
committed by GitHub
parent 0a05c88311
commit 13d6b25f72
100 changed files with 24404 additions and 30 deletions

35
.github/workflows/docs-deploy.yml vendored Normal file
View File

@ -0,0 +1,35 @@
name: Deploy to GitHub Pages
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy to GitHub Pages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
with:
node-version: 18
cache: npm
cache-dependency-path: docs/package-lock.json
- name: Install dependencies
working-directory: ./docs
run: npm ci
- name: Build website
working-directory: ./docs
run: npm run build
# Popular action to deploy to GitHub Pages:
# Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
# Build output to publish to the `gh-pages` branch:
publish_dir: ./docs/build
cname: docs.hanko.io

25
.github/workflows/docs-test-deploy.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: Test deployment
on:
pull_request:
branches:
- main
jobs:
test-deploy:
name: Test deployment
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
with:
node-version: 18
cache: npm
cache-dependency-path: docs/package-lock.json
- name: Install dependencies
working-directory: ./docs
run: npm ci
- name: Test build website
working-directory: ./docs
run: npm run build

View File

@ -77,6 +77,7 @@ The Hanko project consists of
- [hanko-elements](/elements/README.md) - A slick web component made for Hanko backend that features a polished onboarding and login experience and is highly customizable
- [hanko-frontend-sdk](/frontend-sdk/README.md) - A client package for using the Hanko API
- [example](/example) - The quickstart example app, showing off Hanko's strengths and acting as a reference implementation
- [docs](/docs) - The Hanko documentation
# Community
Join our [Slack community](https://www.hanko.io/community) if you have any questions about Hanko or just want to chat about passkeys, authentication, identity, or life in general. You can also [follow us on Twitter](https://twitter.com/hanko_io) or just [reach out via email](https://www.hanko.io/contact).

22
docs/.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
# Dependencies
/node_modules
# Production
/build
# Generated files
.docusaurus
.cache-loader
# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.idea

21
docs/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Hanko.io
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

41
docs/README.md Normal file
View File

@ -0,0 +1,41 @@
# Hanko Documentation
The Hanko documentation is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
### Installation
```
$ npm install
```
### Local Development
```
$ npm run start
```
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
### Build
```
$ npm run build
```
This command generates static content into the `build` directory and can be served using any static contents hosting service.
## Swizzled components
The following components have been [swizzled](https://docusaurus.io/docs/swizzling):
### `DocCard`
- Make icons used in the DocCard customizable via `sidebar_custom_props`
- Make description toggle-able via `sidebar_custom_props`
Uses the following `sidebar_custom_props`:
| Name | Type | Default | Description |
|------------------------|---------|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| docCardIconName | string | undefined | Name of the icon file without file extension. Icons must be placed in `static/img/icons` folder and have an *.svg extension. Uses default images if `undefined`. |
| docCardShowDescription | boolean | undefined/false | Whether to show the description in auto-generated link/category cards. Introduced for SEO reasons such that front-matter `description`s can be used to generate meta tags without being forced to display them in the DocCard. |

3
docs/babel.config.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};

View File

@ -0,0 +1,150 @@
---
title: Angular + Hanko
sidebar_label: Angular
keywords: [angular]
sidebar_custom_props:
docCardIconName: angular
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# Angular
In this guide you will learn how to add authentication to your Angular application using the Hanko custom element.
## Install dependencies
Install the `@teamhanko/hanko-elements` package:
```shell npm2yarn
npm install @teamhanko/hanko-elements
```
## Register custom element with Angular
Angular requires you to explicitly declare that you are using custom elements inside your Angular modules, otherwise
it will fail during build complaining about unknown elements. To do so, import the
[`CUSTOM_ELEMENTS_SCHEMA`](https://angular.io/api/core/CUSTOM_ELEMENTS_SCHEMA), and add it to the `schemas` in your
module:
```js {1,14} title="app.module.ts" showLineNumbers
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule { }
```
## Import & use custom element
Import `@teamhanko/hanko-elements/hanko-auth` in the component where you want to use the Hanko custom element.
Doing so registers the `<hanko-auth>` element with the browser's
[`CustomElementRegistry`](https://developer.mozilla.org/de/docs/Web/API/CustomElementRegistry). Then use the element
in your component template:
```mdx-code-block
<Tabs>
<TabItem value="html" label="login.component.html">
```
```html title="login.component.html" showLineNumbers
<hanko-auth [api]="hankoApi" [lang]="hankoLang"></hanko-auth>
```
```mdx-code-block
</TabItem>
<TabItem value="ts" label="login.component.ts">
```
```js {3,11-12} title="login.component.ts" showLineNumbers
import { Component } from '@angular/core';
import { environment } from '../../../environments/environment';
import '@teamhanko/hanko-elements/hanko-auth';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent {
hankoApi = environment.hankoApi;
hankoLang = environment.hankoLang;
}
```
```mdx-code-block
</TabItem>
</Tabs>
```
## Defining login callbacks
The `<hanko-auth>` element dispatches a custom `success` event on successful login. React to this
event in order to, for example, redirect your users to protected pages in your application.
To do so, you can use Angular's event binding mechanism and supply a callback function that is defined in your component
class directly on the `<hanko-auth>` element:
```mdx-code-block
<Tabs>
<TabItem value="html" label="login.component.html">
```
```html {2} title="login.component.html" showLineNumbers
<hanko-auth
(success)="redirectToProfile()"
[api]="hankoApi"
[lang]="hankoLang">
</hanko-auth>
```
```mdx-code-block
</TabItem>
<TabItem value="ts" label="login.component.ts">
```
```js {3,15-19} title="login.component.ts" showLineNumbers
import { Component } from '@angular/core';
import { environment } from '../../../environments/environment';
import { Router } from '@angular/router';
import '@teamhanko/hanko-elements/hanko-auth';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css'],
})
export class LoginComponent {
hankoApi = environment.hankoApi;
hankoLang = environment.hankoLang;
constructor(private router: Router) {}
redirectToProfile() {
this.router.navigate(['/profile']);
}
}
```
```mdx-code-block
</TabItem>
</Tabs>
```
## Backend request authentication
If you want to authenticate requests in your own backend, please view our [backend guide](/guides/backend).

View File

@ -0,0 +1,60 @@
---
sidebar_label: Backend guide
sidebar_position: 3
description: "Learn how to authenticate requests in your backend by verifying JWTs (JSON Web Token) using a JWK (JSON Web Key Set)."
---
# Backend guide
After a successful login Hanko issues a cookie containing a JSON Web Token
([JWT](https://datatracker.ietf.org/doc/html/rfc7519)). You can use this JWT to authenticate
requests on your backend. To do so, first retrieve the JSON Web Key Set
([JWKS](https://datatracker.ietf.org/doc/html/rfc7517))
containing the public keys used to verify the JSON Web Token (JWT) from the Hanko API's `.well-known/jwks.json` endpoint.
Then use the JWKS to verify the JWT using a library for the programming language of your choice.
The following code shows an example of a custom middleware in a Go-based backend using
[Echo](https://echo.labstack.com/) and the [lestrrat-go/jwx](https://github.com/lestrrat-go/jwx) package:
```go
import (
"context"
"fmt"
"github.com/labstack/echo/v4"
"github.com/lestrrat-go/jwx/v2/jwk"
"github.com/lestrrat-go/jwx/v2/jwt"
"log"
"net/http"
)
func SessionMiddleware(hankoUrl string) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
cookie, err := c.Cookie("hanko")
if err == http.ErrNoCookie {
return c.Redirect(http.StatusTemporaryRedirect, "/unauthorized")
}
if err != nil {
return err
}
// replace "hankoApiURL" with your API URL
set, err := jwk.Fetch(context.Background(), fmt.Sprintf("%v/.well-known/jwks.json", hankoApiURL))
if err != nil {
return err
}
token, err := jwt.Parse([]byte(cookie.Value), jwt.WithKeySet(set))
if err != nil {
return c.Redirect(http.StatusTemporaryRedirect, "/unauthorized")
}
log.Printf("session for user '%s' verified successfully", token.Subject())
c.Set("token", cookie.Value)
c.Set("user", token.Subject())
return next(c)
}
}
}
```

105
docs/docs/guides/next.mdx Normal file
View File

@ -0,0 +1,105 @@
---
title: Next.js + Hanko
sidebar_label: Next.js
keywords: [next, nextjs]
sidebar_custom_props:
docCardIconName: nextjs-dark
---
# Next.js
In this guide you will learn how to add authentication to your Next.js application using the Hanko custom element.
## Install dependencies
Install the `@teamhanko/hanko-elements` package:
```shell npm2yarn
npm install @teamhanko/hanko-elements
```
## Import & use custom element
Import `@teamhanko/hanko-elements/hanko-auth` in the component where you want to use the Hanko custom element.
```jsx title="HankoAuth.jsx" showLineNumbers
import "@teamhanko/hanko-elements/hanko-auth";
export default function HankoAuth() {
return (
<hanko-auth
api={process.env.NEXT_PUBLIC_HANKO_API}
lang={process.env.NEXT_PUBLIC_HANKO_LANG}
/>
);
}
```
If you used this component in your application, the import would attempt to register the `<hanko-auth>` element with the
browser's [`CustomElementRegistry`](https://developer.mozilla.org/de/docs/Web/API/CustomElementRegistry) through a
call to `window.customElements.define()`.
Next.js pre-renders pages on the server but the browser `window` is not available during pre-rendering, so the custom
element registration would fail.
A solution for this is to use Next's [dynamic import](https://nextjs.org/docs/advanced-features/dynamic-import) feature
to dynamically load the component on the client-side and disable server rendering for it:
```jsx title="index.js" showLineNumbers
import dynamic from "next/dynamic";
export default function Home() {
const HankoAuthNoSSR = dynamic(
// replace with path to your component using the <hanko-auth> element
() => import('../components/HankoAuth'),
{ ssr: false },
)
return (
<Suspense fallback={"Loading ..."}>
<HankoAuthNoSSR/>
</Suspense>
)
}
```
## Defining login callbacks
The `<hanko-auth>` element dispatches a custom `success` event on successful login. React to this
event in order to, for example, redirect your users to protected pages in your application.
To do so, create a [`ref`](https://reactjs.org/docs/hooks-reference.html#useref) to obtain access to the `<hanko-auth>`
DOM element and apply an event listener with an appropriate redirect callback:
```jsx {1-2,6-18,22} title="HankoAuth.jsx" showLineNumbers
import React, { useEffect, useRef } from "react";
import { useRouter } from "next/router";
import "@teamhanko/hanko-elements/hanko-auth";
export default function HankoAuth() {
const router = useRouter();
const ref = useRef(null);
const redirectToProfile = () => {
router.replace("/profile");
}
useEffect(() => {
const { current } = ref;
current?.addEventListener("success", redirectToProfile);
return () => current?.removeEventListener("success", redirectToProfile);
}, []);
return (
<hanko-auth
ref={ref}
api={process.env.NEXT_PUBLIC_HANKO_API}
lang={process.env.NEXT_PUBLIC_HANKO_LANG}
/>
);
}
```
## Backend request authentication
If you want to authenticate requests in your own backend, please view our [backend guide](/guides/backend).

View File

@ -0,0 +1,82 @@
---
title: React + Hanko
sidebar_label: React
keywords: [react]
sidebar_custom_props:
docCardIconName: react
---
# React
In this guide you will learn how to add authentication to your React application using the Hanko custom element.
## Install dependencies
Install the `@teamhanko/hanko-elements` package:
```shell npm2yarn
npm install @teamhanko/hanko-elements
```
## Import & use custom element
Import `@teamhanko/hanko-elements/hanko-auth` in the component where you want to use the Hanko custom element.
Doing so registers the `<hanko-auth>` element with the browser's
[`CustomElementRegistry`](https://developer.mozilla.org/de/docs/Web/API/CustomElementRegistry). Then use the element
in your JSX:
```jsx {1,4-7} title="HankoAuth.jsx" showLineNumbers
import "@teamhanko/hanko-elements/hanko-auth";
function HankoAuth() {
return <hanko-auth
api={process.env.NEXT_PUBLIC_HANKO_API}
lang={process.env.NEXT_PUBLIC_HANKO_LANG}
/>;
}
export default HankoAuth;
```
## Defining login callbacks
The `<hanko-auth>` element dispatches a custom `success` event on successful login. React to this
event in order to, for example, redirect your users to protected pages in your application.
To do so, create a [`ref`](https://reactjs.org/docs/hooks-reference.html#useref) to obtain access to the `<hanko-auth>`
DOM element and apply an event listener with an appropriate redirect callback:
```jsx {1-2,6-18,22} title="HankoAuth.jsx" showLineNumbers
import React, { useEffect, useRef } from "react";
import { useNavigate } from "react-router-dom";
import "@teamhanko/hanko-elements/hanko-auth";
function HankoAuth() {
const ref = useRef(null);
const navigate = useNavigate();
const redirectToProfile = () => {
navigate("/profile", { replace: true });
}
useEffect(() => {
const { current } = ref;
current?.addEventListener("success", redirectToProfile);
return () => current?.removeEventListener("success", redirectToProfile);
}, []);
return (
<hanko-auth
ref={ref}
api={process.env.REACT_APP_HANKO_API}
lang={process.env.REACT_APP_HANKO_LANG}
/>
);
}
export default HankoAuth;
```
## Backend request authentication
If you want to authenticate requests in your own backend, please view our [backend guide](/guides/backend).

127
docs/docs/guides/vue.mdx Normal file
View File

@ -0,0 +1,127 @@
---
title: Vue + Hanko
sidebar_label: Vue
keywords: [vue]
sidebar_custom_props:
docCardIconName: vue
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# Vue
In this guide you will learn how to add authentication to your Vue application using the Hanko custom element.
## Install dependencies
Install the `@teamhanko/hanko-elements` package:
```shell npm2yarn
npm install @teamhanko/hanko-elements
```
## Register custom element with Vue
Vue needs to know which elements to treat as custom elements, otherwise it will issue a warning regarding component
resolution. To do so, provide a predicate function that determines which elements are to be considered custom elements
to `compilerOptions.isCustomElement` in your configuration:
```mdx-code-block
<Tabs>
<TabItem value="vite" label="Vite Config">
```
```js {7-9} title="vite.config.js" showLineNumbers
import vue from '@vitejs/plugin-vue'
export default {
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag === "hanko-auth"
}
}
})
]
}
```
```mdx-code-block
</TabItem>
<TabItem value="cli" label="Vue CLI Config">
```
```js {8-10} title="vue.config.js" showLineNumbers
module.exports = {
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options => ({
...options,
compilerOptions: {
isCustomElement: (tag) => tag === "hanko-auth"
}
}))
}
}
```
```mdx-code-block
</TabItem>
</Tabs>
```
## Import & use custom element
Import `@teamhanko/hanko-elements/hanko-auth` in the component where you want to use the Hanko custom element.
Doing so registers the `<hanko-auth>` element with the browser's
[`CustomElementRegistry`](https://developer.mozilla.org/de/docs/Web/API/CustomElementRegistry). Then use the
element in your component template:
```js title="HankoAuth.vue" showLineNumbers
<script setup>
import "@teamhanko/hanko-elements/hanko-auth";
const api = import.meta.env.VITE_HANKO_API;
const lang = import.meta.env.VITE_HANKO_LANG;
</script>
<template>
<hanko-auth :api="api" :lang="lang" />
</template>
```
## Defining login callbacks
The `<hanko-auth>` element dispatches a custom `success` event on successful login. React to this
event in order to, for example, redirect your users to protected pages in your application.
To do so, you can use Vue's [`v-on`](https://vuejs.org/guide/essentials/event-handling.html#listening-to-events)
directive (shorthand: `@`) and supply a callback directly on the `<hanko-auth>` element:
```js {2,8-12,16} title="HankoAuth.vue" showLineNumbers
<script setup>
import { useRouter } from "vue-router";
import "@teamhanko/hanko-elements/hanko-auth";
const api = import.meta.env.VITE_HANKO_API;
const lang = import.meta.env.VITE_HANKO_LANG;
const router = useRouter();
const redirectToProfile = () => {
router.push({ path: "/profile" });
};
</script>
<template>
<hanko-auth @success="redirectToProfile" :api="api" :lang="lang" />
</template>
```
## Backend request authentication
If you want to authenticate requests in your own backend, please view our [backend guide](/guides/backend).

21
docs/docs/intro.md Normal file
View File

@ -0,0 +1,21 @@
---
sidebar_position: 1
slug: /
title: Introduction
---
# :wave: Welcome to Hanko Docs
Hanko is a lightweight, open source user authentication solution that takes you on the journey beyond passwords. For better security, increased conversion rates, and happier users.
## Get started with Hanko
To get started with Hanko, visit the [Hanko project](https://github.com/teamhanko/hanko) on GitHub and follow the instructions to get Hanko up and running locally.
## Integrate Hanko
To integrate Hanko into your project, we are providing [guides](/guides/frontend) for popular frontend frameworks.
## Give feedback
We'd love to hear your thoughts about Hanko, especially if you encounter any problems. Please do not hesitate to reach out. You can find us on
- [Hanko Community Slack](https://www.hanko.io/community)
- [Twitter](https://twitter.com/hanko_io)
## Contribute
Contributions to the Hanko project are appreciated. For more complex topics, we encourage you to talk to us first to avoid misunderstandings. We're actively working on Hanko and may have already started implementing certain features.

162
docs/docusaurus.config.js Normal file
View File

@ -0,0 +1,162 @@
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
const lightCodeTheme = require('prism-react-renderer/themes/github');
const darkCodeTheme = require('prism-react-renderer/themes/dracula');
/** @type {import('@docusaurus/types').Config} */
const config = {
title: 'Hanko Documentation',
tagline: 'Hanko Documentation',
url: 'https://docs.hanko.io',
baseUrl: '/',
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
favicon: 'img/favicon.ico',
// GitHub pages deployment config.
// If you aren't using GitHub pages, you don't need these.
organizationName: 'teamhanko', // Usually your GitHub org/user name.
projectName: 'docs', // Usually your repo name.
trailingSlash: false,
// Even if you don't use internalization, you can use this field to set useful
// metadata like html lang. For example, if your site is Chinese, you may want
// to replace "en" with "zh-Hans".
i18n: {
defaultLocale: 'en',
locales: ['en'],
},
presets: [
[
'redocusaurus',
{
// Plugin Options for loading OpenAPI files
specs: [
{
spec: 'static/spec/api.yaml',
route: '/api',
},
],
// Theme Options for modifying how redoc renders them
theme: {
primaryColor: '#ff2e4c',
primaryColorDark: '#aedfff',
options : {
nativeScrollbars: true,
scrollYOffset: 60,
disableSearch: true,
noAutoAuth: true,
expandResponses: '200',
jsonSampleExpandLevel: 3,
pathInMiddlePanel: false,
requiredPropsFirst: true,
hideDownloadButton: true
},
// Change with your site colors
theme: {
typography: {
fontSize: '16px',
fontWeightRegular: '500',
code: {
fontSize: '13px',
fontFamily: 'Courier, monospace',
}
},
sidebar: {
arrow: {
size: '1.7em',
color: '#7f7f7f'
},
width: '300px',
},
}
},
},
],
[
'classic',
/** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
routeBasePath: '/', // Serve the docs at the site's root
sidebarPath: require.resolve('./sidebars.js'),
remarkPlugins: [require('@docusaurus/remark-plugin-npm2yarn'), {sync: true}],
},
blog: false,
theme: {
customCss: [require.resolve('./src/css/custom.css'), require.resolve('./src/css/redoc.css')]
},
}),
],
],
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
docs: {
sidebar: {
hideable: true
}
},
image: 'img/thumbnail.jpg',
announcementBar: {
id: 'support_us',
content:
'⚠️ This documentation is currently a work in progress, stay tuned for more content! ⚠️',
backgroundColor: '#83ceff',
textColor: '#091E42',
isCloseable: true,
},
colorMode: {
defaultMode: 'dark',
disableSwitch: true,
},
navbar: {
logo: {
alt: 'Hanko Logo',
src: 'img/logo.svg',
href: '/',
},
items: [
{
to: '/',
label: 'Docs',
position: 'left',
activeBaseRegex: '^((?!\/api).)*$'
},
{
to: '/api',
label: 'API',
position: 'left',
},
{
type: 'dropdown',
label: 'SDK',
position: 'left',
items: [
{
to: 'jsdoc/@teamhanko/hanko-frontend-sdk/0.0.1-alpha/index.html',
label: 'Frontend 0.0.1-alpha',
target: '_blank'
}
]
},
{
href: 'https://github.com/teamhanko/hanko',
title: "Visit us on GitHub!",
position: 'right',
className: 'header-github-link',
'aria-label': 'Visit us on GitHub!',
},
],
},
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme,
},
}),
};
module.exports = config;

View File

@ -1,29 +0,0 @@
<html>
<head>
<!-- Load the latest Swagger UI code and style from npm using unpkg.com -->
<script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3/swagger-ui.css"/>
<title>Hanko</title>
</head>
<body>
<div id="swagger-ui"></div> <!-- Div to hold the UI component -->
<script>
window.onload = function () {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "spec/api.yaml",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
})
window.ui = ui
}
</script>
</body>
</html>

22945
docs/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

48
docs/package.json Normal file
View File

@ -0,0 +1,48 @@
{
"name": "@teamhanko/docs",
"version": "0.2.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start --port 3001",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "^2.0.1",
"@docusaurus/preset-classic": "^2.0.1",
"@docusaurus/remark-plugin-npm2yarn": "^2.0.1",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.2.1",
"prism-react-renderer": "^1.3.5",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"redocusaurus": "^1.3.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^2.0.1",
"@tsconfig/docusaurus": "^1.0.5",
"typescript": "^4.7.4"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"engines": {
"node": ">=16.14"
}
}

38
docs/sidebars.js Normal file
View File

@ -0,0 +1,38 @@
/**
* Creating a sidebar enables you to:
- create an ordered group of docs
- render a sidebar for each doc of that group
- provide next/previous navigation
The sidebars can be generated from the filesystem, or explicitly defined here.
Create as many sidebars as you want.
*/
// @ts-check
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
// By default, Docusaurus generates a sidebar from the docs folder structure
// tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
// But you can create a sidebar manually
docs: [
'intro',
{
type: 'category',
label: 'Frontend guides',
link: {
type: 'generated-index',
title: 'Frontend guides',
description: 'Set up authentication for your app in minutes by learning how to integrate Hanko with your preferred frontend framework!',
slug: '/guides/frontend',
keywords: ['guides']
},
items: ['guides/angular', "guides/react", "guides/next", "guides/vue"]
},
'guides/backend'
],
};
module.exports = sidebars;

52
docs/src/css/custom.css Normal file
View File

@ -0,0 +1,52 @@
/**
* Any CSS included here will be global. The classic template
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
*/
/* You can override the default Infima variables here. */
:root {
--ifm-color-primary: #ff2e4c;
--ifm-color-primary-dark: #ff1032;
--ifm-color-primary-darker: #ff0125;
--ifm-color-primary-darkest: #d3001e;
--ifm-color-primary-light: #ff4c66;
--ifm-color-primary-lighter: #ff5b73;
--ifm-color-primary-lightest: #ff8899;
--ifm-code-font-size: 95%;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
[data-theme='dark'] {
--ifm-color-primary: #aedfff;
--ifm-color-primary-dark: #83ceff;
--ifm-color-primary-darker: #6ec6ff;
--ifm-color-primary-darkest: #2dacff;
--ifm-color-primary-light: #d9f0ff;
--ifm-color-primary-lighter: #eef8ff;
--ifm-color-primary-lightest: #ffffff;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
}
html[data-theme='dark'] {
--ifm-background-color: #0b0d0e;
}
.header-github-link:hover {
opacity: 0.6;
}
.header-github-link::before {
content: '';
width: 24px;
height: 24px;
display: flex;
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
no-repeat;
}
[data-theme='dark'] .header-github-link::before {
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
no-repeat;
}

218
docs/src/css/redoc.css Normal file
View File

@ -0,0 +1,218 @@
/* Redoc sidebar menu styles */
.redoc-wrap > .menu-content ul > li {
margin: 0.25rem 0;
}
.redoc-wrap > .menu-content {
padding: 8px;
}
.redoc-wrap > .menu-content ul > li > label {
border-radius: 0.25rem;
color: var(--ifm-menu-color);
cursor: pointer;
display: flex;
line-height: 20px;
justify-content: space-between;
padding: var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal);
}
.main-wrapper .redoc-wrap .menu-content {
border-right: 1px solid var(--ifm-toc-border-color);
}
html[data-theme='dark'] .main-wrapper .redoc-wrap .menu-content {
background-color: #0b0d0e;
}
.redoc-wrap .menu-content label[role=menuitem] {
font-size: 1rem;
align-items: center;
}
html[data-theme='dark'] .redoc-wrap .menu-content label[role=menuitem] {
background-color: #0b0d0e;
}
html[data-theme='dark'] .redoc-wrap .menu-content label[role=menuitem] {
font-size: 1rem;
align-items: center;
background-color: #0b0d0e;
}
.redoc-wrap .menu-content label[role=menuitem].active {
background-color: var(--ifm-menu-color-background-hover) !important;
}
.redoc-wrap .menu-content label[role=menuitem]:hover {
font-size: 1rem;
align-items: center;
background-color: var(--ifm-menu-color-background-hover);
}
html[data-theme='dark'] .redoc-wrap .menu-content label[role=menuitem]:hover {
font-size: 1rem;
align-items: center;
background-color: var(--ifm-menu-color-background-hover);
}
.redoc-wrap .menu-content .operation-type {
margin-top: 0;
}
.redoc-wrap .menu-content ul[role='navigation'] > li:first-child {
margin-top: 0;
}
/* Redoc main content table styles */
.redoc-wrap > .api-content table {
display: table;
font-size: 13px;
}
.redoc-wrap .api-content table tr {
border-top: none;
}
.redoc-wrap .api-content table td[kind=field] {
border-top: none;
border-bottom: none;
border-right: none;
border-left-color: var(--ifm-color-primary);
}
.redoc-wrap .api-content table td[kind=field] span:first-child::before,
.redoc-wrap .api-content table td[kind=field] span:first-child::after {
background-color: var(--ifm-color-primary)
}
.redoc-wrap .api-content table td[kind=field] + td {
border-top: none;
border-left: none;
border-right: none;
}
@media screen and (max-width: 50rem) {
.redoc-wrap .api-content table td[kind=field] + td {
border-left: 1px solid var(--ifm-color-primary);
}
html[data-theme='dark'] .redoc-wrap .api-content table td[kind=field] + td {
border-left: 1px solid var(--ifm-color-primary);
}
}
@media screen and (max-width: 50rem) {
.redoc-wrap .api-content table tr.last td~td {
border-left: none;
}
html[data-theme='dark'] .redoc-wrap .api-content table tr.last td~td {
border-left: none;
}
}
.redoc-wrap .api-content table tr.expanded + tr > td {
border-top: none;
border-bottom: none;
border-right: none;
}
.redoc-wrap .api-content table table tr:nth-child(n) {
background-color: inherit;
}
.redoc-wrap .api-content tr:first-of-type > td[kind="field"] {
background-image: linear-gradient( to bottom, transparent 0%, transparent 22px, var(--ifm-color-primary) 22px, var(--ifm-color-primary) 100% );
border-left-width: 0;
background-position: top left;
background-repeat: no-repeat;
background-size: 1px 100%;
}
.redoc-wrap .api-content tr.last > td[kind="field"] {
background-image: linear-gradient( to bottom, var(--ifm-color-primary) 0%, var(--ifm-color-primary) 22px, transparent 22px, transparent 100% );
}
.redoc-wrap .api-content tr.last:first-child > td[kind="field"] {
background: none;
border-left-color: transparent;
}
.redoc-wrap .api-content table tbody tr table tbody tr > td[colspan] {
border-left-color: var(--ifm-color-primary) !important;
}
html[data-theme='dark'] .redoc-wrap .api-content tr.last:first-child > td[kind="field"] {
background: none;
border-left-color: transparent;
}
html[data-theme='dark'] .redoc-wrap .api-content tr.last > td[kind="field"] {
background-image: linear-gradient( to bottom, var(--ifm-color-primary) 0%, var(--ifm-color-primary) 22px, transparent 22px, transparent 100% );
}
html[data-theme='dark'] .redoc-wrap .api-content table caption {
color: var(--ifm-color-white);
}
html[data-theme='dark'] .redoc-wrap .api-content table tbody tr table {
background: none !important;
}
html[data-theme='dark'] .redoc-wrap .api-content table tbody tr table tbody tr > td[colspan] {
border-left-color: var(--ifm-color-primary) !important;
}
html[data-theme='dark'] .redoc-wrap .api-content table tbody tr table tbody tr > td[colspan] > div {
background: none !important;
}
/* Redoc main content misc styles */
.redoc-wrap a:hover {
color: var(--ifm-color-primary) !important;
text-decoration: underline !important;
}
.redoc-wrap .api-content h3 {
display: block;
font-size: 1.17em;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0;
margin-inline-end: 0;
font-weight: bold;
}
html[data-theme='dark'] .redoc-wrap .api-content h5 ~ svg {
fill: var(--ifm-color-white);
}
.redoc-wrap .api-content h3 ~ div button:not([aria-label="expand properties"]) {
display: flex;
align-items: center;
}
.redoc-wrap .api-content h3 ~ div button:not([aria-label="expand properties"]) span {
padding-left: .5em;
}
.react-tabs__tab-panel--selected button {
display: inline-block !important;
}
/* Code styles */
.redoc-json code {
color: #ffffff;
background-color: transparent;
padding: 0;
}
.redoc-wrap .api-content code {
color: var(--ifm-color-primary);
}
.api-content pre {
background-color: #272C30;
}

View File

@ -0,0 +1,138 @@
import React, {type ReactNode} from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import {
findFirstCategoryLink,
useDocById,
} from '@docusaurus/theme-common/internal';
import isInternalUrl from '@docusaurus/isInternalUrl';
import {translate} from '@docusaurus/Translate';
import useBaseUrl from '@docusaurus/useBaseUrl';
import type {Props} from '@theme/DocCard';
import styles from './styles.module.css';
import type {
PropSidebarItemCategory,
PropSidebarItemLink,
} from '@docusaurus/plugin-content-docs';
function CardContainer({
href,
children,
}: {
href: string;
children: ReactNode;
}): JSX.Element {
return (
<Link
href={href}
className={clsx('card padding--lg', styles.cardContainer)}>
{children}
</Link>
);
}
function CardLayout({
href,
icon,
title,
description,
showDescription
}: {
href: string;
icon: ReactNode;
title: string;
description?: string;
showDescription?: boolean;
}): JSX.Element {
return (
<CardContainer href={href}>
<h2 className={clsx('text--truncate', styles.cardTitle)} title={title}>
{icon} {title}
</h2>
{description && showDescription && (
<p
className={clsx('text--truncate', styles.cardDescription)}
title={description}>
{description}
</p>
)}
</CardContainer>
);
}
function CardCategory({
item,
}: {
item: PropSidebarItemCategory;
}): JSX.Element | null {
const href = findFirstCategoryLink(item);
// Unexpected: categories that don't have a link have been filtered upfront
if (!href) {
return null;
}
const icon = <DocCardIcon item={item}/>
return (
<CardLayout
href={href}
icon={icon}
title={item.label}
description={translate(
{
message: '{count} items',
id: 'theme.docs.DocCard.categoryDescription',
description:
'The default description for a category card in the generated index about how many items this category includes',
},
{count: item.items.length},
)}
showDescription={!!item.customProps.docCardShowDescription}
/>
);
}
function CardLink({item}: {item: PropSidebarItemLink}): JSX.Element {
const icon = <DocCardIcon item={item}/>
const doc = useDocById(item.docId ?? undefined);
return (
<CardLayout
href={item.href}
icon={icon}
title={item.label}
description={doc?.description}
showDescription={!!item.customProps.docCardShowDescription}
/>
);
}
export default function DocCard({item}: Props): JSX.Element {
switch (item.type) {
case 'link':
return <CardLink item={item} />;
case 'category':
return <CardCategory item={item} />;
default:
throw new Error(`unknown item type ${JSON.stringify(item)}`);
}
}
function DocCardIcon({ item }: {item: PropSidebarItemLink | PropSidebarItemCategory}): JSX.Element {
let icon: ReactNode;
if (item.customProps?.docCardIconName) {
const iconName = item.customProps.docCardIconName;
icon = <img alt={`${iconName} icon`} src={useBaseUrl(`/img/icons/${iconName}.svg`)}/>
} else {
icon = item.type === 'category' ? '🗃️' : isInternalUrl(item.href) ? '📄️' : '🔗';
}
return (
<div className={styles.cardIcon}>
{icon}
</div>
)
}

View File

@ -0,0 +1,37 @@
.cardContainer {
--ifm-link-color: var(--ifm-color-emphasis-800);
--ifm-link-hover-color: var(--ifm-color-emphasis-700);
--ifm-link-hover-decoration: none;
box-shadow: 0 1.5px 3px 0 rgb(0 0 0 / 15%);
border: 1px solid var(--ifm-color-emphasis-200);
transition: all var(--ifm-transition-fast) ease;
transition-property: border, box-shadow;
}
.cardContainer:hover {
border-color: var(--ifm-color-primary);
box-shadow: 0 3px 6px 0 rgb(0 0 0 / 20%);
}
.cardContainer *:last-child {
margin-bottom: 0;
}
.cardTitle {
font-size: 1.2rem;
display: flex;
align-items: center;
}
.cardDescription {
font-size: 0.8rem;
}
.cardIcon {
margin-right: 1rem;
width: 2rem;
height: 2rem;
display: flex;
align-items: center;
}

0
docs/static/.nojekyll vendored Normal file
View File

BIN
docs/static/img/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

12
docs/static/img/icons/angular.svg vendored Normal file
View File

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" style="enable-background:new 0 0 250 250;" xml:space="preserve" viewBox="31.9 30 186.2 200">
<style type="text/css">
.st0{fill:#DD0031;}
.st1{fill:#C3002F;}
.st2{fill:#FFFFFF;}
</style>
<g>
<polygon class="st0" points="125,30 125,30 125,30 31.9,63.2 46.1,186.3 125,230 125,230 125,230 203.9,186.3 218.1,63.2 "/>
<polygon class="st1" points="125,30 125,52.2 125,52.1 125,153.4 125,153.4 125,230 125,230 203.9,186.3 218.1,63.2 125,30 "/>
<path class="st2" d="M125,52.1L66.8,182.6h0h21.7h0l11.7-29.2h49.4l11.7,29.2h0h21.7h0L125,52.1L125,52.1L125,52.1L125,52.1 L125,52.1z M142,135.4H108l17-40.9L142,135.4z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 752 B

3
docs/static/img/icons/nextjs-dark.svg vendored Normal file
View File

@ -0,0 +1,3 @@
<svg width="1000" height="1000" viewBox="0 0 1000 1000" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M467.253 0.269139C465.103 0.464613 458.26 1.14878 452.102 1.63747C310.068 14.4411 177.028 91.0671 92.7664 208.841C45.8456 274.325 15.8358 348.605 4.49658 427.284C0.488759 454.748 0 462.86 0 500.098C0 537.336 0.488759 545.448 4.49658 572.912C31.6716 760.666 165.298 918.414 346.53 976.861C378.983 987.319 413.196 994.453 452.102 998.754C467.253 1000.42 532.747 1000.42 547.898 998.754C615.054 991.326 671.945 974.71 728.055 946.073C736.657 941.675 738.319 940.502 737.146 939.525C736.364 938.939 699.707 889.777 655.718 830.352L575.758 722.353L475.562 574.085C420.43 492.572 375.073 425.915 374.682 425.915C374.291 425.818 373.9 491.693 373.705 572.13C373.412 712.97 373.314 718.639 371.554 721.962C369.013 726.751 367.058 728.706 362.952 730.856C359.824 732.42 357.087 732.713 342.327 732.713H325.415L320.919 729.878C317.986 728.021 315.836 725.578 314.37 722.744L312.317 718.345L312.512 522.382L312.805 326.321L315.836 322.509C317.4 320.457 320.723 317.818 323.069 316.547C327.077 314.592 328.641 314.397 345.552 314.397C365.494 314.397 368.817 315.179 373.998 320.848C375.464 322.411 429.717 404.12 494.624 502.541C559.531 600.963 648.289 735.352 691.887 801.324L771.065 921.248L775.073 918.609C810.557 895.543 848.094 862.703 877.81 828.495C941.056 755.877 981.818 667.326 995.503 572.912C999.511 545.448 1000 537.336 1000 500.098C1000 462.86 999.511 454.748 995.503 427.284C968.328 239.53 834.702 81.7821 653.47 23.3352C621.505 12.975 587.488 5.84016 549.365 1.53972C539.98 0.562345 475.367 -0.51276 467.253 0.269139ZM671.945 302.668C676.637 305.014 680.45 309.51 681.818 314.201C682.6 316.743 682.796 371.085 682.6 493.549L682.307 669.281L651.32 621.781L620.235 574.281V446.538C620.235 363.95 620.626 317.525 621.212 315.277C622.776 309.803 626.197 305.503 630.89 302.962C634.897 300.909 636.364 300.714 651.711 300.714C666.178 300.714 668.719 300.909 671.945 302.668Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

37
docs/static/img/icons/react.svg vendored Normal file
View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_2_1_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 490.6 436.9" style="enable-background:new 0 0 490.6 436.9;" xml:space="preserve">
<style type="text/css">
.st0{fill:#61DAFB;}
</style>
<g>
<path class="st0" d="M490.6,218.5c0-32.5-40.7-63.3-103.1-82.4c14.4-63.6,8-114.2-20.2-130.4c-6.5-3.8-14.1-5.6-22.4-5.6v22.3
c4.6,0,8.3,0.9,11.4,2.6c13.6,7.8,19.5,37.5,14.9,75.7c-1.1,9.4-2.9,19.3-5.1,29.4c-19.6-4.8-41-8.5-63.5-10.9
c-13.5-18.5-27.5-35.3-41.6-50c32.6-30.3,63.2-46.9,84-46.9V0l0,0c-27.5,0-63.5,19.6-99.9,53.6c-36.4-33.8-72.4-53.2-99.9-53.2
v22.3c20.7,0,51.4,16.5,84,46.6c-14,14.7-28,31.4-41.3,49.9c-22.6,2.4-44,6.1-63.6,11c-2.3-10-4-19.7-5.2-29
c-4.7-38.2,1.1-67.9,14.6-75.8c3-1.8,6.9-2.6,11.5-2.6V0.5l0,0c-8.4,0-16,1.8-22.6,5.6c-28.1,16.2-34.4,66.7-19.9,130.1
C40.5,155.4,0,186.1,0,218.5c0,32.5,40.7,63.3,103.1,82.4c-14.4,63.6-8,114.2,20.2,130.4c6.5,3.8,14.1,5.6,22.5,5.6
c27.5,0,63.5-19.6,99.9-53.6c36.4,33.8,72.4,53.2,99.9,53.2c8.4,0,16-1.8,22.6-5.6c28.1-16.2,34.4-66.7,19.9-130.1
C450.1,281.7,490.6,250.9,490.6,218.5z M360.4,151.8c-3.7,12.9-8.3,26.2-13.5,39.5c-4.1-8-8.4-16-13.1-24
c-4.6-8-9.5-15.8-14.4-23.4C333.6,146,347.3,148.6,360.4,151.8z M314.6,258.3c-7.8,13.5-15.8,26.3-24.1,38.2c-14.9,1.3-30,2-45.2,2
c-15.1,0-30.2-0.7-45-1.9c-8.3-11.9-16.4-24.6-24.2-38c-7.6-13.1-14.5-26.4-20.8-39.8c6.2-13.4,13.2-26.8,20.7-39.9
c7.8-13.5,15.8-26.3,24.1-38.2c14.9-1.3,30-2,45.2-2c15.1,0,30.2,0.7,45,1.9c8.3,11.9,16.4,24.6,24.2,38
c7.6,13.1,14.5,26.4,20.8,39.8C329,231.8,322.1,245.2,314.6,258.3z M346.9,245.3c5.4,13.4,10,26.8,13.8,39.8
c-13.1,3.2-26.9,5.9-41.2,8c4.9-7.7,9.8-15.6,14.4-23.7C338.5,261.4,342.8,253.3,346.9,245.3z M245.5,352
c-9.3-9.6-18.6-20.3-27.8-32c9,0.4,18.2,0.7,27.5,0.7c9.4,0,18.7-0.2,27.8-0.7C264,331.7,254.7,342.4,245.5,352z M171.1,293.1
c-14.2-2.1-27.9-4.7-41-7.9c3.7-12.9,8.3-26.2,13.5-39.5c4.1,8,8.4,16,13.1,24S166.2,285.5,171.1,293.1z M245,85
c9.3,9.6,18.6,20.3,27.8,32c-9-0.4-18.2-0.7-27.5-0.7c-9.4,0-18.7,0.2-27.8,0.7C226.5,105.3,235.8,94.6,245,85z M171,143.9
c-4.9,7.7-9.8,15.6-14.4,23.7c-4.6,8-8.9,16-13,24c-5.4-13.4-10-26.8-13.8-39.8C142.9,148.7,156.7,146,171,143.9z M80.5,269.1
c-35.4-15.1-58.3-34.9-58.3-50.6s22.9-35.6,58.3-50.6c8.6-3.7,18-7,27.7-10.1c5.7,19.6,13.2,40,22.5,60.9
c-9.2,20.8-16.6,41.1-22.2,60.6C98.6,276.2,89.2,272.8,80.5,269.1z M134.3,412c-13.6-7.8-19.5-37.5-14.9-75.7
c1.1-9.4,2.9-19.3,5.1-29.4c19.6,4.8,41,8.5,63.5,10.9c13.5,18.5,27.5,35.3,41.6,50c-32.6,30.3-63.2,46.9-84,46.9
C141.1,414.6,137.3,413.7,134.3,412z M371.5,335.8c4.7,38.2-1.1,67.9-14.6,75.8c-3,1.8-6.9,2.6-11.5,2.6c-20.7,0-51.4-16.5-84-46.6
c14-14.7,28-31.4,41.3-49.9c22.6-2.4,44-6.1,63.6-11C368.6,316.8,370.4,326.5,371.5,335.8z M410,269.1c-8.6,3.7-18,7-27.7,10.1
c-5.7-19.6-13.2-40-22.5-60.9c9.2-20.8,16.6-41.1,22.2-60.6c9.9,3.1,19.3,6.5,28.1,10.2c35.4,15.1,58.3,34.9,58.3,50.6
C468.3,234.2,445.4,254.1,410,269.1z"/>
<path class="st0" d="M145.1,0.4L145.1,0.4L145.1,0.4z"/>
<circle class="st0" cx="245.2" cy="218.5" r="45.7"/>
<path class="st0" d="M344.8,0.1L344.8,0.1L344.8,0.1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

2
docs/static/img/icons/vue.svg vendored Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 261.76 226.69" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 -76.311 313.34)"><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-75.491l98.16-170.02 98.16 170.02z" fill="#41b883"/></g><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-36.227l58.896-102.01 58.896 102.01z" fill="#34495e"/></g></g></svg>

After

Width:  |  Height:  |  Size: 467 B

11
docs/static/img/logo.svg vendored Normal file
View File

@ -0,0 +1,11 @@
<svg width="105" height="35" viewBox="0 0 105 35" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M28.0484 9.32422V30.3777H24.9845V18.8524C24.9845 18.8524 16.9031 18.8524 12.8772 18.8524C12.8772 19.8094 12.8772 20.7109 12.8772 21.6956C15.9262 21.6956 18.8865 21.6956 21.9207 21.6956C21.9207 22.2504 21.9207 22.708 21.9207 23.1657C21.9207 26.8411 21.9207 30.5303 21.9207 34.2057C21.9207 34.4414 21.9355 34.6217 21.9651 34.7604C25.399 34.2334 28.522 32.8465 31.0678 30.8216C31.0678 27.9368 31.0678 16.5917 31.0678 16.0092C31.053 13.804 30.5202 11.3491 28.0484 9.32422Z" fill="#FF2E4C"/>
<path d="M21.9058 10.2117H24.9696V3.90117C26.8197 4.27564 33.8207 8.56124 34.1019 15.2878V27.7702C36.3665 24.8576 37.7134 21.2793 37.7134 17.396C37.7134 8.63058 30.8901 1.36309 21.9502 0.00390625C21.9206 0.156468 21.9058 0.336768 21.9058 0.572546L21.9058 10.2117Z" fill="#FF2E4C"/>
<path d="M9.79849 25.4401V4.38659H12.8623V15.9119C12.8623 15.9119 20.9438 15.9119 24.9697 15.9119C24.9697 14.955 24.9697 14.0535 24.9697 13.0687C21.9206 13.0687 18.9604 13.0687 15.9262 13.0687C15.9262 12.514 15.9262 12.0563 15.9262 11.5986C15.9262 7.92325 15.9262 4.23403 15.9262 0.558676C15.9262 0.322899 15.9114 0.142599 15.8818 0.00390625C12.4479 0.530938 9.32485 1.91786 6.77905 3.94277C6.77905 6.82758 6.77905 18.1726 6.77905 18.7551C6.79385 20.9742 7.3267 23.4291 9.79849 25.4401Z" fill="#FF2E4C"/>
<path d="M15.9409 24.5663H12.8771V30.8768C11.027 30.5023 4.026 26.2167 3.74478 19.4901V7.00781C1.48021 9.92036 0.133301 13.4986 0.133301 17.382C0.133301 26.1474 6.95663 33.4149 15.8965 34.7741C15.9261 34.6215 15.9409 34.4412 15.9409 34.2054V24.5663Z" fill="#FF2E4C"/>
<path d="M47.7273 24.9719V9.25977H50.1504V15.6112H52.3238V9.25977H54.7469V24.9719H52.3238V17.6656H50.1504V24.9719H47.7273Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M62.2071 9.25977L59.9309 24.9719H62.2952L62.633 22.1652H65.2029L65.5848 24.9719H67.8463L65.4085 9.25977H62.2071ZM63.8666 12.3414L64.9386 20.2409H62.8533L63.8372 12.3414H63.8666Z" fill="white"/>
<path d="M73.0154 24.9719V9.25977H74.9245L78.3021 18.6929L78.1259 14.4103V9.27423H80.314V24.9864H78.5958L75.1301 15.2206L75.2622 19.3439V24.9719H73.0154Z" fill="white"/>
<path d="M85.8503 24.9719V9.25977H88.2734V16.4937L90.6965 9.25977H93.2077L90.5643 17.0146L93.4133 24.9719H90.8433L88.3028 17.6222V24.9575H85.8503V24.9719Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M101.358 25.145C102.592 25.145 103.473 24.7688 104.031 24.0165C104.589 23.2497 104.868 22.1067 104.868 20.5731V13.3826C104.868 11.9647 104.603 10.8941 104.06 10.1562C103.517 9.41834 102.636 9.05664 101.402 9.05664C99.0084 9.05664 97.8188 10.5034 97.8188 13.3826V20.5731C97.8188 22.0922 98.0979 23.2497 98.6706 24.002C99.2433 24.7688 100.139 25.145 101.358 25.145ZM101.358 23.0761C100.917 23.0761 100.624 22.888 100.477 22.5263C100.345 22.1646 100.271 21.528 100.257 20.602V13.2668C100.257 12.5289 100.345 11.9936 100.506 11.6464C100.668 11.3136 100.962 11.14 101.373 11.14C101.784 11.14 102.063 11.2992 102.21 11.6464C102.357 11.9936 102.43 12.5434 102.43 13.2813V20.602C102.43 21.4991 102.357 22.1356 102.224 22.5118C102.092 22.888 101.799 23.0761 101.358 23.0761Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
docs/static/img/thumbnail.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

7
docs/tsconfig.json Normal file
View File

@ -0,0 +1,7 @@
{
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@tsconfig/docusaurus/tsconfig.json",
"compilerOptions": {
"baseUrl": "."
}
}

View File

@ -23,7 +23,7 @@
"format": "pretty-quick --staged",
"build": "microbundle --globals @github/webauthn-json=webauthnJson --tsconfig ./tsconfig.json",
"dev": "microbundle watch",
"docs": "jsdoc -r -c jsdoc.json -d ../docs/jsdoc -P package.json -R README.md --pedantic"
"docs": "jsdoc -r -c jsdoc.json -d ../docs/static/jsdoc -P package.json -R README.md --pedantic"
},
"description": "A package for simplifying UI integration with the Hanko API. It is meant for use in browsers only.",
"repository": "github:teamhanko/hanko",