Skip to main content
Glama
alexander-zuev

Kollektiv | Your private LLM knowledgebase

login.ts5.13 kB
import { AppRoutes } from "@/web/routes"; import { base } from "@/web/templates/base"; import type { ClientInfo } from "@cloudflare/workers-oauth-provider"; import type { Context } from "hono"; import { html } from "hono/html"; /** Authorised login providers */ export enum LoginProvider { GITHUB = "github", GOOGLE = "google", MAGIC_LINK = "magic-link", } /** Common outline-variant classes */ const outlineBtn = "w-full py-3 px-4 cursor-pointer bg-muted text-muted-foreground hover:text-foreground " + "border border-border rounded-md font-medium hover:bg-muted/90 transition-colors " + "flex items-center justify-center gap-2 " + "disabled:hover:text-muted-foreground disabled:bg-muted disabled:cursor-not-allowed "; /** Provider metadata used to build the buttons */ const OAUTH_PROVIDERS: { id: LoginProvider; label: string; icon: string }[] = [ { id: LoginProvider.GITHUB, label: "Login with GitHub", icon: "ph-github-logo" }, { id: LoginProvider.GOOGLE, label: "Login with Google", icon: "ph-google-logo" }, ]; export const loginScreen = (clientInfo: ClientInfo, tx: string) => { /* Helper for OAuth buttons */ const renderOAuthButton = ({ id, label, icon }: (typeof OAUTH_PROVIDERS)[number]) => html` <form method="POST" action="${AppRoutes.LOGIN}?tx=${tx}" onsubmit=" this.querySelectorAll('button[type=submit]') .forEach(btn => { btn.disabled = true; btn.classList.add('bg-muted/90', 'cursor-not-allowed' ,'hover:text-muted-foreground/90'); }); "> <input type="hidden" name="provider" value="${id}"/> <button type="submit" name="button" value="${id}" class="${outlineBtn}"> <i class="ph ${icon} text-lg"></i> ${label} </button> </form> `; return html` <div class="flex w-full justify-center p-8"> <div class="max-w-lg w-full rounded-lg border border-border bg-card p-6 text-center flex flex-col gap-4 items-center" > <i class="ph ph-sign-in text-5xl text-primary mt-4"></i> <h1 class="text-2xl text-center text-foreground"> Login to authorize <strong>${clientInfo?.clientName}</strong> </h1> <p class="text-base text-center text-foreground/80 mb-2"> You’re connecting your Kollektiv account so that <strong>${clientInfo?.clientName || "your IDE/client"}</strong> can securely use Kollektiv MCP on your behalf. Choose any sign-in method below. </p> <!-- OAuth providers --> <div class="w-full space-y-4"> ${OAUTH_PROVIDERS.map(renderOAuthButton)} </div> <!-- divider --> <div class="flex items-center w-full my-4"> <div class="flex-grow border-t border-border"></div> <span class="px-3 text-sm text-muted-foreground">OR CONTINUE WITH</span> <div class="flex-grow border-t border-border"></div> </div> <!-- Magic-link form --> <form method="POST" action="${AppRoutes.LOGIN}?tx=${tx}" onsubmit=" this.querySelectorAll('button[type=submit]') .forEach(btn => { btn.disabled = true; btn.classList.add('bg-muted/90', 'cursor-not-allowed', 'hover:text-muted-foreground/90'); }); " class="w-full space-y-4"> <input type="hidden" name="provider" value="${LoginProvider.MAGIC_LINK}"/> <div> <label for="email" class="block text-sm font-medium text-foreground mb-1 text-left" >Email</label > <input type="email" id="email" name="email" required class="w-full px-3 py-2 border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary bg-card text-foreground" /> </div> <button type="submit" name="button" value="${LoginProvider.MAGIC_LINK}" class="${outlineBtn}" > <i class="ph ph-paper-plane text-lg"></i> Send Magic Link </button> </form> </div> </div> `; }; export async function renderLoginScreen(c: Context, client: ClientInfo, tx: string) { const content = await loginScreen(client, tx); const pageTitle = `Log in to authorize ${client?.clientName || "Application"}`; return c.html(base(content, pageTitle)); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/alexander-zuev/kollektiv-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server