iblai-auth

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

/iblai-auth

/iblai-auth

Add ibl.ai SSO authentication to a vanilla Next.js app. After completion, unauthenticated users are redirected to login.iblai.app and returned with a session -- no API tokens to manage.
Do NOT ask the user for their tenant key. The CLI reads
PLATFORM
from
iblai.env
automatically. If
iblai.env
exists with a real
PLATFORM
value, just run
iblai add auth
(no flag needed). Otherwise use the placeholder:
iblai add auth --platform your-platform
If
.env.local
already has
NEXT_PUBLIC_MAIN_TENANT_KEY
set to a real value (not a placeholder like
your-tenant
,
your-platform
,
your-tenant-key
,
test-tenant
,
main
, or empty), keep that value.
iblai.env
is NOT a
.env.local
replacement — it only holds the 3 shorthand variables (
DOMAIN
,
PLATFORM
,
TOKEN
). Next.js still reads its runtime env vars from
.env.local
.
Use
pnpm
as the default package manager. Fall back to
npm
if pnpm is not installed. The generated app should live in the current directory, not in a subdirectory.
为原生Next.js应用添加ibl.ai SSO身份验证。配置完成后,未认证的用户会被重定向到login.iblai.app,登录完成后会带着会话返回应用,无需管理API令牌。
请勿向用户索要租户密钥。CLI会自动读取iblai.env中的
PLATFORM
变量。如果iblai.env存在且包含有效的
PLATFORM
值,只需运行
iblai add auth
(无需参数)。否则使用占位符形式:
iblai add auth --platform your-platform
如果
.env.local
中已经将
NEXT_PUBLIC_MAIN_TENANT_KEY
设为有效值(不是
your-tenant
your-platform
your-tenant-key
test-tenant
main
这类占位符,也不是空值),请保留原有值。
iblai.env
并不是
.env.local
的替代品——它只存储3个简写变量(
DOMAIN
PLATFORM
TOKEN
)。Next.js仍然会从
.env.local
读取运行时环境变量。
默认使用
pnpm
作为包管理器,如果未安装pnpm则回退到
npm
。生成的应用应当放在当前目录下,不要放在子目录中。

Prerequisites

前置要求

Already have auth? If you used
iblai startapp agent
, auth is already set up -- skip this skill.
Want a complete app from scratch? Create in a temp directory and copy back:
iblai startapp agent -o iblai-init
cp -a iblai-init/<app-name>/. . && rm -rf iblai-init
cp .env.example .env.local
pnpm install && pnpm dev
If
iblai.env
has
PLATFORM
, the CLI reads it automatically. Otherwise pass
--platform your-platform
.
This skill is for adding auth to a vanilla Next.js app (
npx create-next-app@latest my-app --yes
) or an existing project.
  • Next.js 14+ with App Router (
    app/
    directory)
  • Node.js 18+
  • iblai
    CLI available (
    iblai --version
    )
已经配置过认证? 如果你使用过
iblai startapp agent
命令,认证已经提前配置好了,可以跳过本教程。
想要从零搭建完整应用? 可以先在临时目录创建再复制回来:
iblai startapp agent -o iblai-init
cp -a iblai-init/<app-name>/. . && rm -rf iblai-init
cp .env.example .env.local
pnpm install && pnpm dev
如果
iblai.env
中存在
PLATFORM
变量,CLI会自动读取,否则需要传入
--platform your-platform
参数。
本教程适用于为原生Next.js应用(通过
npx create-next-app@latest my-app --yes
创建)或现有项目添加认证。
  • Next.js 14+ 版本,使用App Router(
    app/
    目录)
  • Node.js 18+ 版本
  • 可用的
    iblai
    CLI(可执行
    iblai --version
    验证)

Installing the CLI

安装CLI

If
iblai
is not available:
pip (recommended):
bash
pip install iblai-app-cli
npx:
bash
npx @iblai/cli --version
如果没有可用的
iblai
命令:
pip安装(推荐):
bash
pip install iblai-app-cli
npx安装:
bash
npx @iblai/cli --version

Use npx @iblai/cli as prefix: npx @iblai/cli add auth --platform your-tenant

使用时添加npx @iblai/cli前缀:npx @iblai/cli add auth --platform your-tenant


**Build from source -- macOS / Linux** (Python 3.11+, pip, git, make):

```bash
git clone https://github.com/iblai/iblai-app-cli.git
cd iblai-app-cli
make -C .iblai install
cd -   # back to your project
If
iblai
is not found after install, add
~/.local/bin
to your PATH:
bash
export PATH="$HOME/.local/bin:$PATH"
To make permanent, add the line to
~/.bashrc
or
~/.zshrc
.
Build from source -- Windows (Python 3.11+, pip, git):
powershell
git clone https://github.com/iblai/iblai-app-cli.git
cd iblai-app-cli
pip install -e .iblai/
cd -
If
iblai
is not found, ensure Python Scripts is in your PATH. Typically at
%APPDATA%\Python\Python311\Scripts\
.

**从源码构建——macOS / Linux**(需要Python 3.11+、pip、git、make):

```bash
git clone https://github.com/iblai/iblai-app-cli.git
cd iblai-app-cli
make -C .iblai install
cd -   # 回到你的项目目录
如果安装后找不到
iblai
命令,请将
~/.local/bin
添加到PATH中:
bash
export PATH="$HOME/.local/bin:$PATH"
要永久生效,可将上述行添加到
~/.bashrc
~/.zshrc
文件中。
从源码构建——Windows(需要Python 3.11+、pip、git):
powershell
git clone https://github.com/iblai/iblai-app-cli.git
cd iblai-app-cli
pip install -e .iblai/
cd -
如果找不到
iblai
命令,请确认Python的Scripts目录已添加到PATH中,通常路径为
%APPDATA%\Python\Python311\Scripts\

Step 0: Check for CLI Updates

步骤0:检查CLI更新

Before running any
iblai
command, ensure the CLI is up to date. Run
iblai --version
to check the current version, then upgrade directly:
  • pip:
    pip install --upgrade iblai-app-cli
  • npm:
    npm install -g @iblai/cli@latest
This is safe to run even if already at the latest version.
运行任何
iblai
命令前,请确保CLI是最新版本。运行
iblai --version
查看当前版本,然后直接升级:
  • pip方式:
    pip install --upgrade iblai-app-cli
  • npm方式:
    npm install -g @iblai/cli@latest
即使已经是最新版本,运行升级命令也是安全的。

Step 1: Check Environment

步骤1:检查环境

Before proceeding, check for a
iblai.env
in the project root. Look for
PLATFORM
,
DOMAIN
, and
TOKEN
variables. If the file does not exist or is missing these variables, tell the user: "You need an
iblai.env
with your platform configuration. Download the template and fill in your values:
curl -o iblai.env https://raw.githubusercontent.com/iblai/vibe/refs/heads/main/iblai.env
"
If
PLATFORM
is set to a real value (not
your-platform
), the CLI will read it automatically — no
--platform
flag needed in Step 3. Otherwise use the placeholder.
继续操作前,请检查项目根目录是否存在
iblai.env
文件,确认其中包含
PLATFORM
DOMAIN
TOKEN
变量。如果文件不存在或者缺少这些变量,告知用户: "你需要一个包含平台配置的
iblai.env
文件。下载模板并填写你的配置:
curl -o iblai.env https://raw.githubusercontent.com/iblai/vibe/refs/heads/main/iblai.env
"
如果
PLATFORM
设为有效值(不是
your-platform
),CLI会自动读取,步骤3无需添加
--platform
参数,否则使用占位符形式。

Step 2: Customize Auth Interface

步骤2:自定义认证界面

STOP here. You MUST ask the user these questions before proceeding to Step 3. Do NOT skip this step.
请在此处暂停。进入步骤3前,你必须先向用户确认以下问题,请勿跳过该步骤。

Fetch platform name

获取平台名称

First, read
PLATFORM
and
TOKEN
from
iblai.env
, then fetch the platform metadata to get the platform name:
bash
curl -s "https://api.{domain}/dm/api/core/orgs/{platform}/metadata/" \
  -H "Authorization: Api-Token {token}"
Use the
platform_name
field from the response as the auth title.
首先,从
iblai.env
读取
PLATFORM
TOKEN
,然后拉取平台元数据获取平台名称:
bash
curl -s "https://api.{domain}/dm/api/core/orgs/{platform}/metadata/" \
  -H "Authorization: Api-Token {token}"
使用返回结果中的
platform_name
字段作为认证页面的标题

Ask the user

询问用户

Ask: "Briefly describe what your app does"
If the user skips or doesn't want to answer, use the platform name as
AUTH_DISPLAY_TITLE
and leave
AUTH_DISPLAY_DESCRIPTION
empty. If the user provides a description, generate a headline and tagline from it.
Use
https://ibl.ai/images/iblai-logo.png
as the default logo (favicon, display logo, and side panel logo).
Remaining fields use fixed defaults:
  • Footer credit — Always
    "Powered by {{logo}}"
    (the
    {{logo}}
    placeholder renders the ibl.ai logo)
  • Privacy policy URL — Always
    "https://ibl.ai/privacy-policy"
  • Terms of use URL — Always
    "https://ibl.ai/terms-of-use"
  • Display images — Leave empty (
    []
    )
  • Password-only login — Default
    false
询问:"请简单描述你的应用功能"
如果用户跳过或者不想回答,使用平台名称作为
AUTH_DISPLAY_TITLE
AUTH_DISPLAY_DESCRIPTION
留空。如果用户提供了描述,基于该描述生成标题和标语。
使用
https://ibl.ai/images/iblai-logo.png
作为默认logo(favicon、展示logo、侧边栏logo)。
其余字段使用固定默认值:
  • 页脚版权信息 —— 固定为
    "Powered by {{logo}}"
    {{logo}}
    占位符会渲染为ibl.ai的logo)
  • 隐私政策链接 —— 固定为
    "https://ibl.ai/privacy-policy"
  • 使用条款链接 —— 固定为
    "https://ibl.ai/terms-of-use"
  • 展示图片 —— 留空(
    []
  • 仅密码登录 —— 默认
    false

Save to
iblai.env

保存到
iblai.env

After generating the fields, append them to
iblai.env
so the user can review and edit before the API call:
bash
undefined
生成所有字段后,将它们追加到
iblai.env
中,方便用户在调用API前查看和编辑:
bash
undefined

Auth interface (edit before proceeding)

Auth interface (edit before proceeding)

AUTH_TITLE=<platform_name from API> AUTH_LOGO=https://ibl.ai/images/iblai-logo.png AUTH_DISPLAY_TITLE=<platform_name from API> AUTH_DISPLAY_DESCRIPTION= AUTH_FOOTER_CREDIT=Powered by {{logo}} AUTH_PRIVACY_POLICY_URL=https://ibl.ai/privacy-policy AUTH_TERMS_OF_USE_URL=https://ibl.ai/terms-of-use AUTH_PASSWORD_ONLY=false

Tell the user: "I've saved the generated auth settings to `iblai.env`.
Review them and edit if needed, then let me know to continue."

STOP and wait for the user to confirm before proceeding with the API calls.
Re-read `iblai.env` to pick up any edits the user made.

After confirmation, use `PLATFORM` and `TOKEN` from `iblai.env` for all
API calls. All API requests use this header:
Authorization: Api-Token <token>
undefined
AUTH_TITLE=<platform_name from API> AUTH_LOGO=https://ibl.ai/images/iblai-logo.png AUTH_DISPLAY_TITLE=<platform_name from API> AUTH_DISPLAY_DESCRIPTION= AUTH_FOOTER_CREDIT=Powered by {{logo}} AUTH_PRIVACY_POLICY_URL=https://ibl.ai/privacy-policy AUTH_TERMS_OF_USE_URL=https://ibl.ai/terms-of-use AUTH_PASSWORD_ONLY=false

告知用户:"我已经将生成的认证配置保存到`iblai.env`中,请查看并按需编辑,完成后告知我继续操作。"

继续调用API前请暂停并等待用户确认,重新读取`iblai.env`获取用户修改后的配置。

确认后,所有API调用都使用`iblai.env`中的`PLATFORM`和`TOKEN`,所有API请求都携带以下请求头:
Authorization: Api-Token <token>
undefined

Upload images first

优先上传图片

If
AUTH_LOGO
is a local file path, upload it via:
bash
curl -X POST "https://api.{domain}/dm/api/core/platforms/{platform}/public-image-assets/" \
  -H "Authorization: Api-Token {token}" \
  -F "image=@{file_path}" \
  -F "category={category}"
Upload the logo three times with different categories. If
AUTH_LOGO
is already a URL (like the default), use it directly in the metadata payload without uploading.
ImageCategory
Favicon
auth_spa_favicon
Display logo
auth_spa_logo
Side panel logo
auth_spa_slide_panel_logo
Display images (each)
auth_spa_display_image
The POST response returns a JSON object. Extract the
file
field — that is the URL to use in the metadata payload.
If the user provided a URL (not a local file), use it directly in the metadata payload without uploading.
如果
AUTH_LOGO
本地文件路径,通过以下接口上传:
bash
curl -X POST "https://api.{domain}/dm/api/core/platforms/{platform}/public-image-assets/" \
  -H "Authorization: Api-Token {token}" \
  -F "image=@{file_path}" \
  -F "category={category}"
logo需要上传3次,分别对应不同的分类。如果
AUTH_LOGO
已经是URL(比如默认值),无需上传,直接在元数据请求体中使用该URL即可。
图片类型分类值
Favicon
auth_spa_favicon
展示logo
auth_spa_logo
侧边栏logo
auth_spa_slide_panel_logo
展示图片(每张)
auth_spa_display_image
POST请求返回的JSON对象中,提取
file
字段——该值就是元数据请求体中要使用的URL。
如果用户提供的是URL(不是本地文件),无需上传,直接在元数据请求体中使用该URL即可。

PUT the metadata

提交元数据

After all images are uploaded, assemble the payload and PUT to:
PUT https://api.{domain}/dm/api/core/orgs/{platform}/metadata/
Authorization: Api-Token {token}
Content-Type: application/json
The payload has two identical keys —
auth_web_skillsai
and
auth_web_mentorai
— both containing the same configuration:
json
{
  "auth_web_skillsai": {
    "title": "User's Title",
    "favicon": "https://...uploaded-logo-url...",
    "display_logo": "https://...uploaded-logo-url...",
    "footer_credit": "Powered by {{logo}}",
    "display_images": [],
    "terms_of_use_url": "https://ibl.ai/terms-of-use",
    "display_title_info": "Generated headline",
    "privacy_policy_url": "https://ibl.ai/privacy-policy",
    "display_description_info": "Generated description",
    "display_slide_panel_logo": "https://...uploaded-logo-url...",
    "authorize_only_password_login": false
  },
  "auth_web_mentorai": {
    "title": "User's Title",
    "favicon": "https://...uploaded-logo-url...",
    "display_logo": "https://...uploaded-logo-url...",
    "footer_credit": "Powered by {{logo}}",
    "display_images": [],
    "terms_of_use_url": "https://ibl.ai/terms-of-use",
    "display_title_info": "Generated headline",
    "privacy_policy_url": "https://ibl.ai/privacy-policy",
    "display_description_info": "Generated description",
    "display_slide_panel_logo": "https://...uploaded-logo-url...",
    "authorize_only_password_login": false
  }
}
Always use ibl.ai's privacy policy and terms of use URLs. Generate the headline and description from the user's app description. Set
authorize_only_password_login
to
false
.
After a successful PUT (200), tell the user: "Your login page has been customized! Changes will appear on your next login at https://login.{domain}".
所有图片上传完成后,组装请求体,PUT到以下地址:
PUT https://api.{domain}/dm/api/core/orgs/{platform}/metadata/
Authorization: Api-Token {token}
Content-Type: application/json
请求体包含两个相同的键——
auth_web_skillsai
auth_web_mentorai
,两者的配置完全一致:
json
{
  "auth_web_skillsai": {
    "title": "User's Title",
    "favicon": "https://...uploaded-logo-url...",
    "display_logo": "https://...uploaded-logo-url...",
    "footer_credit": "Powered by {{logo}}",
    "display_images": [],
    "terms_of_use_url": "https://ibl.ai/terms-of-use",
    "display_title_info": "Generated headline",
    "privacy_policy_url": "https://ibl.ai/privacy-policy",
    "display_description_info": "Generated description",
    "display_slide_panel_logo": "https://...uploaded-logo-url...",
    "authorize_only_password_login": false
  },
  "auth_web_mentorai": {
    "title": "User's Title",
    "favicon": "https://...uploaded-logo-url...",
    "display_logo": "https://...uploaded-logo-url...",
    "footer_credit": "Powered by {{logo}}",
    "display_images": [],
    "terms_of_use_url": "https://ibl.ai/terms-of-use",
    "display_title_info": "Generated headline",
    "privacy_policy_url": "https://ibl.ai/privacy-policy",
    "display_description_info": "Generated description",
    "display_slide_panel_logo": "https://...uploaded-logo-url...",
    "authorize_only_password_login": false
  }
}
请始终使用ibl.ai的隐私政策和使用条款链接,基于用户的应用描述生成标题和描述,将
authorize_only_password_login
设为
false
PUT请求成功(返回200)后,告知用户:"你的登录页面已经自定义完成!下次访问https://login.{domain}登录时就会看到更新后的效果。"

Step 3: Run the Generator

步骤3:运行生成器

bash
cd your-nextjs-app
bash
cd your-nextjs-app

If iblai.env has PLATFORM, the CLI reads it automatically

如果iblai.env中存在PLATFORM,CLI会自动读取

iblai add auth
iblai add auth

Or pass explicitly (overrides iblai.env)

或者显式传入(会覆盖iblai.env中的配置)

iblai add auth --platform your-platform
iblai add auth --platform your-platform

Or via npx (when published)

或者通过npx运行(发布后可用)

npx @iblai/cli add auth --platform your-platform

The platform key sets `NEXT_PUBLIC_MAIN_TENANT_KEY` in `.env.local`.
The CLI reads `PLATFORM` from `iblai.env` automatically. Pass `--platform`
only if you want to override it or don't have an `iblai.env`.

The generator creates 7 files and patches `next.config`, `globals.css`, and `.env.local`.
It auto-detects `src/` directory layout and places files accordingly.
npx @iblai/cli add auth --platform your-platform

平台密钥会设置到`.env.local`的`NEXT_PUBLIC_MAIN_TENANT_KEY`字段中。CLI会自动读取`iblai.env`中的`PLATFORM`,仅当你想要覆盖配置或者没有`iblai.env`文件时才需要传入`--platform`参数。

生成器会创建7个文件,并修改`next.config`、`globals.css`和`.env.local`文件,它会自动检测`src/`目录结构并将文件放到对应位置。

Step 4: Install Dependencies

步骤4:安装依赖

bash
pnpm install
The generator adds these to
package.json
:
  • @iblai/iblai-js
    -- SDK (auth, data layer, UI components)
  • @reduxjs/toolkit
    +
    react-redux
    -- state management (SDK uses RTK Query)
  • sonner
    -- toast notifications
  • lucide-react
    -- icons
bash
pnpm install
生成器会在
package.json
中添加以下依赖:
  • @iblai/iblai-js
    -- SDK(包含认证、数据层、UI组件)
  • @reduxjs/toolkit
    +
    react-redux
    -- 状态管理(SDK使用RTK Query)
  • sonner
    -- 吐司通知
  • lucide-react
    -- 图标

Step 5: Wire Providers into Layout

步骤5:在布局中引入Provider

Open
app/layout.tsx
and wrap
{children}
with the generated
IblaiProviders
.
If you have no existing providers:
tsx
import { IblaiProviders } from "@/providers/iblai-providers";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <IblaiProviders>{children}</IblaiProviders>
      </body>
    </html>
  );
}
If you have existing providers (e.g., custom contexts):
tsx
import { IblaiProviders } from "@/providers/iblai-providers";
import { MyProvider } from "./my-provider";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <IblaiProviders>
          <MyProvider>
            {children}
          </MyProvider>
        </IblaiProviders>
      </body>
    </html>
  );
}
IblaiProviders
must be the outermost provider -- it contains Redux, Auth, and Tenant providers that other components depend on. Place your own providers inside it.
打开
app/layout.tsx
,使用生成的
IblaiProviders
包裹
{children}
如果没有现有Provider:
tsx
import { IblaiProviders } from "@/providers/iblai-providers";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <IblaiProviders>{children}</IblaiProviders>
      </body>
    </html>
  );
}
如果有现有Provider(比如自定义context):
tsx
import { IblaiProviders } from "@/providers/iblai-providers";
import { MyProvider } from "./my-provider";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <IblaiProviders>
          <MyProvider>
            {children}
          </MyProvider>
        </IblaiProviders>
      </body>
    </html>
  );
}
IblaiProviders
必须是最外层的Provider——它包含其他组件依赖的Redux、Auth和Tenant provider,请将你自己的Provider放在它内部。

Step 6: Configure Environment

步骤6:配置环境变量

If the CLI read
PLATFORM
from
iblai.env
or you passed
--platform
, the tenant key is already set in
.env.local
. Verify with:
bash
iblai config show
Otherwise, edit
.env.local
(created by the generator) or use the CLI:
bash
iblai config set NEXT_PUBLIC_MAIN_TENANT_KEY your-tenant
The default API URLs point to
iblai.app
and are set automatically.
如果CLI从
iblai.env
读取了
PLATFORM
或者你传入了
--platform
参数,租户密钥已经自动设置到
.env.local
中,可以通过以下命令验证:
bash
iblai config show
否则,编辑生成器创建的
.env.local
文件,或者使用CLI设置:
bash
iblai config set NEXT_PUBLIC_MAIN_TENANT_KEY your-tenant
默认的API地址指向
iblai.app
,会自动设置。

Step 7: Import SDK Styles

步骤7:导入SDK样式

Verify
app/globals.css
has the SDK imports (the generator patches this automatically):
css
@import '@iblai/iblai-js/web-containers/styles';
@source "../node_modules/@iblai/iblai-js/dist/web-containers/source";
If these lines are missing, add them near the top of
globals.css
.
确认
app/globals.css
中已经导入了SDK样式(生成器会自动修改该文件):
css
@import '@iblai/iblai-js/web-containers/styles';
@source "../node_modules/@iblai/iblai-js/dist/web-containers/source";
如果缺少这些行,请将它们添加到
globals.css
的顶部附近。

Step 8: Replace Default Home Page

步骤8:替换默认首页

After adding auth, check if
app/page.tsx
still has the default Next.js content (look for
next/image
,
vercel.svg
,
Vercel
, or
Get started by editing
). If it does, replace it with the ibl.ai home page:
bash
iblai add homepage
If the user has already customized their home page, skip this step.
添加认证后,检查
app/page.tsx
是否还保留Next.js默认内容(查找
next/image
vercel.svg
Vercel
或者
Get started by editing
)。如果是,替换为ibl.ai首页:
bash
iblai add homepage
如果用户已经自定义过首页,可以跳过该步骤。

Step 9: Start Dev Server

步骤9:启动开发服务器

Start the dev server so the user can see the result:
bash
pnpm dev
  1. Open http://localhost:3000
  2. You should be redirected to https://login.iblai.app
  3. Log in (or create a free account)
  4. You'll be returned to your app with a fully authenticated session
  5. Check browser localStorage -- you should see
    axd_token
    ,
    userData
    ,
    tenants
启动开发服务器,让用户可以查看效果:
bash
pnpm dev
  1. 打开 http://localhost:3000
  2. 你会被重定向到 https://login.iblai.app
  3. 登录(或者免费创建账号)
  4. 你会被带回你的应用,获得完整的认证会话
  5. 查看浏览器localStorage——你会看到
    axd_token
    userData
    tenants
    字段

What Was Generated

生成的文件

FilePurpose
app/sso-login-complete/page.tsx
SSO callback -- stores tokens from URL into localStorage
lib/iblai/config.ts
Environment variable accessors (API URLs, tenant key, auth URL)
lib/iblai/storage-service.ts
localStorage wrapper implementing the SDK's StorageService interface
lib/iblai/auth-utils.ts
redirectToAuthSpa()
,
hasNonExpiredAuthToken()
,
handleLogout()
store/iblai-store.ts
Redux store with
coreApiSlice
,
mentorReducer
,
mentorMiddleware
providers/iblai-providers.tsx
Provider chain: ReduxProvider > AuthProvider > TenantProvider
文件路径用途
app/sso-login-complete/page.tsx
SSO回调页面——将URL中的令牌存储到localStorage
lib/iblai/config.ts
环境变量访问器(API地址、租户密钥、认证地址)
lib/iblai/storage-service.ts
localStorage封装,实现SDK的StorageService接口
lib/iblai/auth-utils.ts
包含
redirectToAuthSpa()
hasNonExpiredAuthToken()
handleLogout()
方法
store/iblai-store.ts
Redux store,包含
coreApiSlice
mentorReducer
mentorMiddleware
providers/iblai-providers.tsx
Provider链:ReduxProvider > AuthProvider > TenantProvider

What Was Patched

修改的文件

  • next.config.ts
    -- webpack
    resolve.alias
    to deduplicate
    @reduxjs/toolkit
    ,
    turbopack: {}
    for Next.js 16+. Without the dedup, SDK components use a different
    ReactReduxContext
    and RTK Query hooks silently return
    undefined
    with zero HTTP requests.
  • globals.css
    -- SDK base styles import.
  • .env.local
    -- API URLs, auth URL, tenant key, WebSocket URL.
  • next.config.ts
    —— 添加webpack
    resolve.alias
    配置去重
    @reduxjs/toolkit
    ,Next.js 16+版本添加
    turbopack: {}
    配置。如果没有去重,SDK组件会使用不同的
    ReactReduxContext
    ,RTK Query钩子会静默返回
    undefined
    ,不会发起任何HTTP请求。
  • globals.css
    —— 导入SDK基础样式。
  • .env.local
    —— 添加API地址、认证地址、租户密钥、WebSocket地址。

Advanced: Route Groups

进阶:路由分组

For production apps, consider moving the SSO callback outside the auth providers using Next.js route groups:
app/
├── (auth)/
│   └── sso-login-complete/page.tsx   ← Outside providers (no AuthProvider wrapper)
└── (app)/
    ├── layout.tsx                     ← IblaiProviders wraps only this group
    └── page.tsx
This prevents the SSO callback deadlock where
AuthProvider
blocks rendering before tokens are stored. The generator places the callback at
app/sso-login-complete/
(flat, no route group) which works for simple apps.
For the route group pattern, see the reference implementation: https://github.com/iblai/iblai-app-cli/tree/main/examples/iblai-agent-app
对于生产环境应用,建议使用Next.js路由分组将SSO回调页面移到认证Provider外部:
app/
├── (auth)/
│   └── sso-login-complete/page.tsx   ← 在Provider外部(没有AuthProvider包裹)
└── (app)/
    ├── layout.tsx                     ← IblaiProviders仅包裹该分组
    └── page.tsx
这可以避免SSO回调死锁:即
AuthProvider
在令牌存储前就阻塞渲染。生成器默认将回调页面放在
app/sso-login-complete/
(平级,没有路由分组),可以满足简单应用的需求。
关于路由分组模式,可以参考实现示例: https://github.com/iblai/iblai-app-cli/tree/main/examples/iblai-agent-app

Troubleshooting

问题排查

"Unknown server error" with custom-domains on localhost

本地环境自定义域名出现"Unknown server error"

The SDK calls
/api/custom-domains?domain=localhost
as part of tenant detection. This fails on localhost but is harmless -- the tenant is resolved from
NEXT_PUBLIC_MAIN_TENANT_KEY
in
.env.local
instead. You can safely ignore this console error during local development.
SDK会调用
/api/custom-domains?domain=localhost
进行租户检测,该请求在本地环境会失败,但无影响——租户会转而从
.env.local
NEXT_PUBLIC_MAIN_TENANT_KEY
字段解析。本地开发时可以忽略该控制台错误。

SDK components show undefined / no API requests

SDK组件显示undefined / 没有API请求

@reduxjs/toolkit
must be deduplicated in
next.config.ts
. Without the webpack alias, the SDK's components use a different
ReactReduxContext
than your app's
StoreProvider
, so RTK Query hooks silently return
undefined
.
Verify your next.config has:
javascript
config.resolve.alias['@reduxjs/toolkit'] = rtkDir;
@reduxjs/toolkit
必须在
next.config.ts
中配置去重。如果没有webpack别名,SDK组件会使用和你的应用
StoreProvider
不同的
ReactReduxContext
,导致RTK Query钩子静默返回
undefined
确认你的next.config包含以下配置:
javascript
config.resolve.alias['@reduxjs/toolkit'] = rtkDir;

Auth redirect loops

认证重定向循环

The SSO callback page (
app/sso-login-complete/page.tsx
) must NOT be wrapped by
AuthProvider
. If it is,
AuthProvider
detects "no tokens" and redirects to login before the callback can store the tokens -- creating an infinite loop.
If this happens, use the route group pattern described above to separate the SSO callback from the authenticated routes.
SSO回调页面(
app/sso-login-complete/page.tsx
)不能被
AuthProvider
包裹。如果被包裹,
AuthProvider
会检测到"无令牌",在回调存储令牌前就重定向到登录页,造成无限循环。
如果出现该问题,使用上面提到的路由分组模式,将SSO回调和认证路由分开。

Blank screen after login

登录后页面空白

Check that
.env.local
has
NEXT_PUBLIC_MAIN_TENANT_KEY
set. Without it, the tenant resolution falls back to custom-domain detection which fails on localhost, leaving the app in a broken state.
检查
.env.local
是否设置了
NEXT_PUBLIC_MAIN_TENANT_KEY
。如果没有,租户解析会回退到自定义域名检测,在本地环境会失败,导致应用处于异常状态。

Next Steps

后续步骤

After auth is set up, add more features:
bash
iblai add chat           # AI chat widget (requires agent ID)
Other features are built using skills -- ask your AI assistant to use:
SkillWhat It Adds
/iblai-chat
AI chat widget
/iblai-profile
User profile dropdown + settings page
/iblai-account
Account/organization settings page
/iblai-analytics
Analytics dashboard page
/iblai-notification
Notification bell + center page
For the complete reference implementation with all features: https://github.com/iblai/iblai-app-cli/tree/main/examples/iblai-agent-app
Brand guidelines: BRAND.md
认证配置完成后,可以添加更多功能:
bash
iblai add chat           # AI聊天组件(需要agent ID)
其他功能可以通过skill实现——告知你的AI助手使用以下skill:
Skill添加的功能
/iblai-chat
AI聊天组件
/iblai-profile
用户头像下拉菜单 + 设置页
/iblai-account
账号/组织设置页
/iblai-analytics
数据分析看板页
/iblai-notification
通知铃铛 + 通知中心页
品牌指南: BRAND.md