chore: rename HANZO_IAM_ env vars to IAM_ prefix

Drop HANZO_ prefix from all IAM environment variable names for
consistency across the Hanzo ecosystem. Also renames IS_HANZO_IAM_ENABLED
to IS_IAM_ENABLED.
This commit is contained in:
Hanzo Dev
2026-03-10 16:31:44 -07:00
parent 5cec25a302
commit 8220c9f42a
22 changed files with 106 additions and 111 deletions
+4 -4
View File
@@ -26,10 +26,10 @@ NEXTAUTH_SECRET="xxxxxxxxxx"
NEXTAUTH_URL="http://localhost:3000"
# Hanzo IAM OAuth (required for production)
HANZO_IAM_URL="https://hanzo.id"
HANZO_IAM_CLIENT_ID=""
HANZO_IAM_CLIENT_SECRET=""
# HANZO_IAM_PROVIDER_NAME="Hanzo"
IAM_URL="https://hanzo.id"
IAM_CLIENT_ID=""
IAM_CLIENT_SECRET=""
# IAM_PROVIDER_NAME="Hanzo"
## Auth Optional (deprecated — use Hanzo IAM above)
# GOOGLE_CLIENT_ID=""
@@ -11,7 +11,7 @@ const OnboardingPage = async () => {
<div className="border-rounded w-full max-w-2xl border bg-white p-10 shadow">
<div className="mb-5">
<h1 className="text-2xl font-semibold tracking-tight">
Welcome to Hanzo Captable!
Welcome to {process.env.NEXT_PUBLIC_APP_NAME || "Hanzo Captable"}!
</h1>
<p className="text-sm text-muted-foreground">
You are almost there. Please complete the form below to continue
+1 -1
View File
@@ -20,7 +20,7 @@ const OnboardingPage = async () => {
<div className="border-rounded w-full max-w-2xl border bg-white p-10 shadow">
<div className="mb-5">
<h1 className="text-2xl font-semibold tracking-tight">
Welcome to Hanzo Captable
Welcome to {process.env.NEXT_PUBLIC_APP_NAME || "Hanzo Captable"}
</h1>
<p className="text-sm text-muted-foreground">
You are almost there. Please complete the form below to continue
+2 -1
View File
@@ -1,3 +1,4 @@
import { APP_NAME } from "@/lib/branding";
import SignInForm from "@/components/onboarding/signin";
import { getServerComponentAuthSession } from "@/server/auth";
import type { Metadata } from "next";
@@ -5,7 +6,7 @@ import { redirect } from "next/navigation";
export const metadata: Metadata = {
title: "Login",
description: "Login to Hanzo Captable",
description: `Login to ${APP_NAME}`,
};
export default async function SignIn() {
+2 -1
View File
@@ -1,3 +1,4 @@
import { APP_NAME } from "@/lib/branding";
import SignUpForm from "@/components/onboarding/signup";
import { getServerComponentAuthSession } from "@/server/auth";
import type { Metadata } from "next";
@@ -5,7 +6,7 @@ import { redirect } from "next/navigation";
export const metadata: Metadata = {
title: "Sign Up",
description: "Sign Up to Hanzo Captable",
description: `Sign Up to ${APP_NAME}`,
};
export default async function SignIn() {
+4 -2
View File
@@ -1,12 +1,14 @@
import { ApiReference } from "@scalar/nextjs-api-reference";
const appName = process.env.NEXT_PUBLIC_APP_NAME || "Hanzo Captable";
const config = {
spec: {
url: "/api/v1/schema",
},
metaData: {
title: "Hanzo Captable API Docs",
description: "Hanzo Captable API Docs",
title: `${appName} API Docs`,
description: `${appName} API Docs`,
},
};
+4 -4
View File
@@ -1,4 +1,5 @@
import logo from "@/assets/logo.svg";
import { APP_DESCRIPTION, APP_NAME } from "@/lib/branding";
import { PublicEnvScript } from "@/components/public-env-script";
import ScreenSize from "@/components/screen-size";
import { constants } from "@/lib/constants";
@@ -15,11 +16,10 @@ import { Toaster } from "sonner";
export const metadata: Metadata = {
title: {
template: "%s | Hanzo Captable",
default: "Hanzo Captable",
template: `%s | ${APP_NAME}`,
default: APP_NAME,
},
description:
"Hanzo Captable is an open source cap table management tool that does not sell your data.",
description: APP_DESCRIPTION,
icons: [{ rel: "icon", url: logo.src }],
metadataBase: new URL(constants.url),
};
+1 -1
View File
@@ -12,7 +12,7 @@ const EmptyOverview = ({ firstName, publicCompanyId }: EmptyOverviewProps) => {
return (
<EmptyState
icon={<RiPieChartFill />}
title={`Welcome to Hanzo Captable ${firstName && `, ${firstName}`} 👋`}
title={`Welcome to ${process.env.NEXT_PUBLIC_APP_NAME || "Hanzo Captable"} ${firstName && `, ${firstName}`} 👋`}
subtitle={
<span className="text-muted-foreground">
We will get you setup with your Captable in no time.
+1 -1
View File
@@ -55,7 +55,7 @@ export function VerifyMemberForm({ memberId, token }: VerifyMemberFormProps) {
<div className="flex flex-col gap-y-4">
<div className="flex flex-col gap-y-2 text-center">
<h1 className="text-3xl font-semibold">
Welcome to our Hanzo Captable! 👋
Welcome! 👋
</h1>
<p className="text-muted-foreground">
Enter your information to complete onboarding
@@ -1,4 +1,5 @@
import { CaptableLogo } from "@/components/common/logo";
import { APP_NAME } from "@/lib/branding";
interface LoginFormHeaderProps {
page?: string;
@@ -13,8 +14,8 @@ export function AuthFormHeader({ page }: LoginFormHeaderProps) {
<h1 className="mb-2 text-2xl font-semibold tracking-tight">
{page === "signup"
? "Signup to Hanzo Captable"
: "Login to Hanzo Captable"}
? `Signup to ${APP_NAME}`
: `Login to ${APP_NAME}`}
</h1>
</div>
);
+21 -32
View File
@@ -4,39 +4,28 @@ import { Button } from "@/components/ui/button";
import { signIn } from "next-auth/react";
import { AuthFormHeader } from "../auth-form-header";
const SignInForm = () => {
async function signInWithHanzo() {
await signIn("hanzo-iam", { callbackUrl: "/onboarding" });
}
const IAM_PROVIDER_NAME =
process.env.NEXT_PUBLIC_IAM_PROVIDER_NAME || "Hanzo";
return (
<div className="flex h-screen items-center justify-center bg-gradient-to-br from-indigo-50 via-white to-cyan-100">
<div className="grid w-full max-w-md grid-cols-1 gap-5 rounded-xl border bg-white p-10 shadow">
<AuthFormHeader page="signin" />
<Button
type="button"
onClick={signInWithHanzo}
className="bg-red-500 hover:bg-red-600 text-white"
>
<svg
className="mr-2 h-4 w-4"
viewBox="0 0 67 67"
fill="currentColor"
role="img"
aria-label="Hanzo"
>
<title>Hanzo</title>
<path d="M22.21 67V44.6369H0V67H22.21Z" />
<path d="M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z" />
<path d="M22.21 0H0V22.3184H22.21V0Z" />
<path d="M66.7198 0H44.5098V22.3184H66.7198V0Z" />
<path d="M66.7198 67V44.6369H44.5098V67H66.7198Z" />
</svg>
Sign in with <span className="font-bold">Hanzo</span>
</Button>
</div>
</div>
);
const SignInForm = () => {
async function signInWithIAM() {
await signIn("hanzo-iam", { callbackUrl: "/onboarding" });
}
return (
<div className="flex h-screen items-center justify-center bg-gradient-to-br from-indigo-50 via-white to-cyan-100">
<div className="grid w-full max-w-md grid-cols-1 gap-5 rounded-xl border bg-white p-10 shadow">
<AuthFormHeader page="signin" />
<Button
type="button"
onClick={signInWithIAM}
className="bg-red-500 hover:bg-red-600 text-white"
>
Sign in with <span className="font-bold">{IAM_PROVIDER_NAME}</span>
</Button>
</div>
</div>
);
};
export default SignInForm;
+31 -41
View File
@@ -4,48 +4,38 @@ import { Button } from "@/components/ui/button";
import { signIn } from "next-auth/react";
import { AuthFormHeader } from "../auth-form-header";
const SignUpForm = () => {
async function signInWithHanzo() {
await signIn("hanzo-iam", { callbackUrl: "/onboarding" });
}
const IAM_PROVIDER_NAME =
process.env.NEXT_PUBLIC_IAM_PROVIDER_NAME || "Hanzo";
return (
<div className="flex h-screen items-center justify-center bg-gradient-to-br from-indigo-50 via-white to-cyan-100">
<div className="grid w-full max-w-md grid-cols-1 gap-5 rounded-xl border bg-white p-10 shadow">
<AuthFormHeader page="signup" />
<Button
type="button"
onClick={signInWithHanzo}
className="bg-red-500 hover:bg-red-600 text-white"
>
<svg
className="mr-2 h-4 w-4"
viewBox="0 0 67 67"
fill="currentColor"
role="img"
aria-label="Hanzo"
>
<title>Hanzo</title>
<path d="M22.21 67V44.6369H0V67H22.21Z" />
<path d="M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z" />
<path d="M22.21 0H0V22.3184H22.21V0Z" />
<path d="M66.7198 0H44.5098V22.3184H66.7198V0Z" />
<path d="M66.7198 67V44.6369H44.5098V67H66.7198Z" />
</svg>
Sign up with <span className="font-bold">Hanzo</span>
</Button>
<span className="text-center text-sm text-gray-500">
Already have an account?{" "}
<a
href="/login"
className="underline underline-offset-4 hover:text-primary"
>
Login
</a>
</span>
</div>
</div>
);
const SignUpForm = () => {
async function signInWithIAM() {
await signIn("hanzo-iam", { callbackUrl: "/onboarding" });
}
return (
<div className="flex h-screen items-center justify-center bg-gradient-to-br from-indigo-50 via-white to-cyan-100">
<div className="grid w-full max-w-md grid-cols-1 gap-5 rounded-xl border bg-white p-10 shadow">
<AuthFormHeader page="signup" />
<Button
type="button"
onClick={signInWithIAM}
className="bg-red-500 hover:bg-red-600 text-white"
>
Sign up with{" "}
<span className="font-bold">{IAM_PROVIDER_NAME}</span>
</Button>
<span className="text-center text-sm text-gray-500">
Already have an account?{" "}
<a
href="/login"
className="underline underline-offset-4 hover:text-primary"
>
Login
</a>
</span>
</div>
</div>
);
};
export default SignUpForm;
+3 -2
View File
@@ -1,3 +1,4 @@
import { APP_NAME } from "@/lib/branding";
import { Avatar, AvatarImage } from "@/components/ui/avatar";
import { Card } from "@/components/ui/card";
import Link from "next/link";
@@ -36,12 +37,12 @@ export const SharePageLayout = ({
<p>
Powered by{" "}
<Link
href={`https://captable.hanzo.ai?utm_source=${company.name}&utm_medium=${medium}&utm_campaign=powered_by`}
href={`${process.env.NEXT_PUBLIC_APP_URL || "https://captable.hanzo.ai"}?utm_source=${company.name}&utm_medium=${medium}&utm_campaign=powered_by`}
target="_blank"
rel="noopener noreferrer"
className="font-bold text-teal-500 hover:underline"
>
Hanzo Captable
{APP_NAME}
</Link>
</p>
</div>
+2 -2
View File
@@ -83,7 +83,7 @@ const UpdatesEditor = ({
},
content: [
{
text: "Here's a quick update on what's been happening at Hanzo Captable this month. We're excited to share that we've hit a major milestone! Our team has been hard at work and we're proud to announce that we've successfully launched our new product feature.",
text: "Here's a quick update on what's been happening at your company this month. We're excited to share that we've hit a major milestone! Our team has been hard at work and we're proud to announce that we've successfully launched our new product feature.",
type: "text",
styles: {},
},
@@ -156,7 +156,7 @@ const UpdatesEditor = ({
},
content: [
{
text: "The Hanzo Captable Team",
text: "The your company Team",
type: "text",
styles: {},
},
+1 -1
View File
@@ -1 +1 @@
export const IS_HANZO_IAM_ENABLED = true;
export const IS_IAM_ENABLED = true;
+1 -1
View File
@@ -43,7 +43,7 @@ export const MemberInviteEmail = ({
</Text>
<Text className="text-[14px] leading-[24px] text-black">
<strong>{invitedBy}</strong> has invited you to join{" "}
<strong>{companyName}</strong> on <strong>Hanzo Captable</strong>.
<strong>{companyName}</strong> on <strong>{process.env.NEXT_PUBLIC_APP_NAME || "Captable"}</strong>.
</Text>
<Section className="mb-[32px] mt-[32px]">
+1 -1
View File
@@ -84,7 +84,7 @@ export const ShareDataRoomEmail = ({
ShareDataRoomEmail.PreviewProps = {
senderName: "John Doe",
recipientName: "Will Smith",
companyName: "Hanzo Captable",
companyName: "Captable",
dataRoom: "Q1 2024 Financials",
link: "https://captable.hanzo.ai/...",
} as ShareDataRoomEmailProps;
+1 -1
View File
@@ -85,7 +85,7 @@ export const ShareUpdateEmail = ({
ShareUpdateEmail.PreviewProps = {
senderName: "John Doe",
recipientName: "Will Smith",
companyName: "Hanzo Captable",
companyName: "Captable",
updateTitle: "Q1 2024 Financials",
link: "https://captable.hanzo.ai/...",
} as ShareUpdateEmailProps;
+9
View File
@@ -0,0 +1,9 @@
export const APP_NAME =
process.env.NEXT_PUBLIC_APP_NAME || "Hanzo Captable";
export const APP_DESCRIPTION =
process.env.NEXT_PUBLIC_APP_DESCRIPTION ||
"Open source cap table management";
export const IAM_PROVIDER_NAME =
process.env.NEXT_PUBLIC_IAM_PROVIDER_NAME || "Hanzo";
export const COMPANY_NAME =
process.env.NEXT_PUBLIC_COMPANY_NAME || "Hanzo AI, Inc.";
+5 -4
View File
@@ -1,8 +1,9 @@
import { APP_DESCRIPTION, APP_NAME } from "@/lib/branding";
export const constants = {
title: "Hanzo Captable",
url: "https://captable.hanzo.ai",
description:
"Hanzo Captable is the Open Source alternative to Carta and Pulley.",
title: APP_NAME,
url: process.env.NEXT_PUBLIC_APP_URL || "https://captable.hanzo.ai",
description: APP_DESCRIPTION,
twitter: {
url: "https://twitter.com/captableinc",
},
+1 -1
View File
@@ -34,7 +34,7 @@ export function PublicAPI() {
openapi: "3.1.0",
info: {
version: "v1",
title: "Hanzo Captable API (v1)",
title: `${process.env.NEXT_PUBLIC_APP_NAME || "Hanzo Captable"} API (v1)`,
},
servers: [{ url: `${env.NEXTAUTH_URL}` }],
}));
+7 -7
View File
@@ -12,20 +12,20 @@ import { type TPrismaOrTransaction, db } from "@/server/db";
import type { OAuthConfig } from "next-auth/providers/oauth";
import { cache } from "react";
const HANZO_IAM_URL = process.env.HANZO_IAM_URL;
const HANZO_IAM_CLIENT_ID = process.env.HANZO_IAM_CLIENT_ID;
const HANZO_IAM_CLIENT_SECRET = process.env.HANZO_IAM_CLIENT_SECRET;
const IAM_URL = process.env.IAM_URL;
const IAM_CLIENT_ID = process.env.IAM_CLIENT_ID;
const IAM_CLIENT_SECRET = process.env.IAM_CLIENT_SECRET;
// biome-ignore lint/suspicious/noExplicitAny: IAM profile shape varies
function HanzoIAMProvider(): OAuthConfig<any> {
const issuer = HANZO_IAM_URL || "https://hanzo.id";
const issuer = IAM_URL || "https://hanzo.id";
return {
id: "hanzo-iam",
name: process.env.HANZO_IAM_PROVIDER_NAME || "Hanzo",
name: process.env.IAM_PROVIDER_NAME || "Hanzo",
type: "oauth",
wellKnown: `${issuer}/.well-known/openid-configuration`,
clientId: HANZO_IAM_CLIENT_ID || "",
clientSecret: HANZO_IAM_CLIENT_SECRET || "",
clientId: IAM_CLIENT_ID || "",
clientSecret: IAM_CLIENT_SECRET || "",
authorization: { params: { scope: "openid profile email" } },
idToken: false,
userinfo: { url: `${issuer}/oauth/userinfo` },