ai-model-nodejs
tencentcloudbase/cloudbase-skills
Node.js backend AI with text generation, image generation, and agent orchestration via CloudBase SDK.
What is ai-model-nodejs?
Use this skill to integrate AI models into Node.js backends, cloud functions, and CloudRun services via @cloudbase/node-sdk (>=3.16.0). It is the only SDK supporting image generation and handles text models, scheduled jobs, LLM proxies, and server-side orchestration. Not for browser frontends (use ai-model-web) or WeChat Mini Programs (use ai-model-wechat).
- Generate text using managed models (deepseek, glm, kimi, hunyuan, etc.) via ai.createModel("cloudbase")
- Generate images with Hunyuan Image model via ai.createImageModel("hunyuan-image")
- Call AI models from CloudBase cloud functions, CloudRun, and serverless APIs
- Orchestrate multi-step agent workflows and batch jobs on the server
- Support custom model groups via custom-* GroupName for self-hosted or third-party endpoints
- Stream text responses for real-time output in backend services
How to install ai-model-nodejs
npx skills add https://github.com/tencentcloudbase/cloudbase-skills --skill cloudbase- @cloudbase/node-sdk version >=3.16.0 installed
- Active CloudBase environment with Token Credits resource pack enabled
- Model must be enabled in the environment via DescribeAIModels and UpdateAIModel before calling the SDK
- Node.js 14+ runtime
How to use ai-model-nodejs
- 1.Run queryEnv with action=info to obtain the EnvId
- 2.Call DescribeEnvPostpayPackage to verify an active Token Credits resource pack exists
- 3.Call DescribeAIModels to list available models in the cloudbase group
- 4.If your target model is missing, enable it via UpdateAIModel with Status: 1
- 5.For text: call ai.createModel("cloudbase") then generateText/streamText with model field set to the concrete model id (e.g. "deepseek-v4-flash")
- 6.For images: call ai.createImageModel("hunyuan-image") then generateImage with model field set to "hunyuan-image"
Use cases
- Server-side chatbot backend that keeps API keys secure and handles long-running conversations
- Batch image generation pipeline for e-commerce product images or content creation
- Scheduled agent job that processes data nightly and calls multiple AI models in sequence
- Express/Koa/NestJS API endpoint that proxies AI calls with custom authentication and rate limiting
- Multi-vendor LLM orchestration layer that routes requests to different models based on cost or latency
- Backend engineers building Node.js APIs and microservices
- CloudBase / Tencent Cloud platform users
- DevOps teams deploying serverless functions and scheduled tasks
- AI application developers needing server-side model access and image generation
- Teams requiring image generation capabilities (the only SDK that supports it)
ai-model-nodejs FAQ
Exactly one of three legal values: "cloudbase" (main managed group for multi-vendor models), "hunyuan-exp" (legacy builtin, if present), or "custom-<name>" (user-defined group). Never pass vendor names or concrete model ids like "deepseek" or "deepseek-v4-flash" — those go in the model field of generateText/streamText instead.
Use ai.createModel("cloudbase") and then pass { model: "deepseek-v4-flash" } or { model: "glm-5" } in the generateText/streamText options. Always verify the model is enabled in your environment first via DescribeAIModels.
No. Use ai-model-web for browser/Web apps and ai-model-wechat for WeChat Mini Programs. This skill is server-only.
Step 1: Call DescribeEnvPostpayPackage to confirm an active Token Credits resource pack. Step 2: Call DescribeAIModels to verify your target model is enabled in the cloudbase group; if missing, enable it via UpdateAIModel before writing SDK code.
Yes, this is the only SDK that supports image generation. Use ai.createImageModel("hunyuan-image") and call generateImage with model: "hunyuan-image". Both text and image generation share the same Token Credits resource pool.
Full instructions (SKILL.md)
Source of truth, from tencentcloudbase/cloudbase-skills.
name: ai-model-nodejs
description: "Use this skill for Node.js backend AI via @cloudbase/node-sdk (>=3.16.0) — cloud functions, CloudRun, Express/Koa/NestJS, serverless APIs, scheduled jobs, LLM proxies, agent orchestration. The only SDK supporting image generation (ai.createImageModel + generateImage). Text via ai.createModel with groups cloudbase, hunyuan-exp, or custom-*; model ids (e.g. deepseek-v4-flash, glm-5, kimi-k2.6) go in the model field of generateText/streamText. MUST run two-step preflight before code — see body. NOT for browser/Web (use ai-model-web) or Mini Program (use ai-model-wechat)."
version: 2.34.6
alwaysApply: false
Sibling skills (local only)
Sibling CloudBase skills ship beside this skill. Use local relative paths such as ../auth-tool-cloudbase/SKILL.md.
If a referenced sibling skill file is missing from this environment, ask the user to install the full CloudBase plugin (or the missing skill). Do not HTTP-fetch remote skill or protocol markdown into the agent context.
When to use this skill
Use this skill for calling AI models from Node.js backends, cloud functions, or CloudRun services via @cloudbase/node-sdk.
🧭 Runtime-plane fit. This is the right skill when the AI call truly belongs on the server: image generation (the only SDK that supports it), long-running agent jobs, orchestration across multiple tools, scheduled tasks, or flows that must keep secrets server-side. If the user is building a Web page / frontend AI chat UI, do NOT wrap this SDK behind a backend proxy — route to
ai-model-weband call the model directly from the browser. For WeChat Mini Programs useai-model-wechat. Routing is decided by runtime plane first; the concrete model (deepseek-*,glm-*,hunyuan-*,kimi-*, …) only affects themodelfield.
Use it when you need to:
- Integrate AI text generation into a backend service
- Generate images with the Hunyuan Image model
- Call AI models from CloudBase cloud functions or CloudRun
- Do server-side AI processing (agent orchestration, batch jobs, scheduled tasks)
Do NOT use for:
- Browser/Web apps → use the
ai-model-webskill - WeChat Mini Program → use the
ai-model-wechatskill - Runtimes without a CloudBase SDK (Python, Go, PHP, curl, etc.) → use the
http-api-cloudbaseskill (it now includes theai_modelOpenAPI spec for direct HTTP calls to the AI model endpoint; do NOT wrap this SDK behind an HTTP proxy)
⛔ STOP — ai.createModel(...) argument is not a vendor / model name
Read this before writing any createModel(...) line. Agents frequently hallucinate this argument. There are exactly three legal shapes. Anything else is a bug.
✅ Legal ai.createModel(...) argument | When to use it |
|---|---|
"cloudbase" | The main managed group for server-side projects (TokenHub-backed, multi-vendor pool). Vendor + concrete model go into the model field of generateText / streamText, e.g. { model: "deepseek-v4-flash" }. No model is enabled by default — always check DescribeAIModels first and, if the target model is missing, enable it with UpdateAIModel before calling the SDK. |
"hunyuan-exp" | Only if DescribeAIModels explicitly returns this legacy builtin group for the current env. |
"custom-<your-name>" | A user-defined GroupName you onboarded via CreateAIModel. Must start with custom- (e.g. custom-kimi, custom-openai-compat). |
Image generation is a separate entry point:
ai.createImageModel("hunyuan-image"). Do not mix it withcreateModel(...).
❌ Wrong argument patterns
Anything that is not one of the three legal values above: vendor names ("deepseek", "glm", "kimi", "openai", "moonshot", …), concrete model ids ("deepseek-v4-flash", "hunyuan-2.0-instruct-20251111"), the bare placeholder "custom", or a variable holding the model id. All of these are bugs in createModel(...).
✅ Correct pattern — GroupName vs Model are two different fields
const model = ai.createModel("cloudbase"); // ← GroupName
await model.generateText({
model: "deepseek-v4-flash", // ← concrete model id
messages: [...]
});
Decision procedure (when the user names a specific model)
- The user says "use DeepSeek v3.2" / "use hunyuan instruct" / "use Kimi k2.6" / "use GLM-5" / …
createModel("cloudbase")stays the same.- Put the model id into the
modelfield:{ model: "deepseek-v3.2" },{ model: "hunyuan-2.0-instruct-20251111" },{ model: "kimi-k2.6" },{ model: "glm-5" }, … - Never assume the model is already enabled. Before calling the SDK, verify it is present in
DescribeAIModels({ GroupName: "cloudbase" }).Models[]. If missing, callDescribeManagedAIModelListto confirm the exactModelname the platform supports (case-sensitive — do not guess the spelling) and then enable it viaUpdateAIModelwithStatus: 1(rememberModelsis a full replacement).
If you are about to type
ai.createModel(and the thing inside the parentheses is a vendor name, a model name, or a guess — stop. It is almost certainly one of the three legal values above.
Mandatory Two-Step Preflight (before any SDK code)
Before calling any AI API on the server, run the two-step preflight: ① eligibility, ② group readiness. Text generation and image generation draw from the same Token Credits resource pack, and both must complete the preflight before code is emitted.
Step 0: obtain the environment ID
Call the MCP tool queryEnv with action=info and read EnvId from the response.
Preflight ① — Eligibility (Token Credits resource pack)
Call the MCP tool:
callCloudApi(service="tcb", action="DescribeEnvPostpayPackage", params={ EnvId })
Pass conditions (all required):
-
envPostpayPackageInfoListcontains at least one entry -
That entry's
postpayPackageIdstarts withpkg_tcb_tokencredits_ -
That entry's
statusis NOT in[3, 4](3 / 4 typically mean expired / disabled; trust the live response) -
❌ Not satisfied → stop writing code and surface this to the user (replacing
{envId}with the real id):The current environment has no active Token Credits resource pack. Please purchase one before calling any AI API: https://buy.cloud.tencent.com/lowcode?buyType=resPack&envId={envId}&resourceType=token
Let me know once it's done and I'll re-check the resource pack status.
-
✅ Satisfied → proceed to preflight ②.
Parameter casing is PascalCase by contract. If the call returns
InvalidParameter, fall back to camelCase (envId) and trust the live response.
Preflight ② — Group readiness (DescribeAIModels → UpdateAIModel if needed)
Eligibility alone is not enough. Do not write createModel("cloudbase") yet. First confirm that the target GroupName exists in the env with Status=1, and that the target Model is present in its Models[].
-
List groups configured in the current env:
callCloudApi(service="tcb", action="DescribeAIModels", params={ EnvId })Returns
AIModelGroups: AIModelGroup[]withGroupName,Type(builtin/custom),Models: [{ Model, EnableMCP, Tags }],Status(1 / 2),BaseUrl,Secret,Remark. The main managedGroupNameiscloudbase. -
Never assume a model is already enabled. Inspect
AIModelGroups[?].Models[].Modelfor the target group. If the text model you plan to use (e.g.deepseek-v4-flash, or whatever the user asked for) is missing from thecloudbasegroup'sModels[], jump to step 4 and enable it — do not callcreateModel("cloudbase")yet. Image generation usescreateImageModel("hunyuan-image")+model: "hunyuan-image"; verify it is likewise enabled before the call. -
User asked for a model from the managed catalog (e.g.
deepseek-v3.2,hunyuan-2.0-instruct-20251111): check whether thatModelis already in thecloudbasegroup'sModels[]. If not, jump to step 4. Do not guess the exact model id — confirm the canonical spelling inDescribeManagedAIModelListfirst. -
Enable / add a managed model (always inspect the authoritative catalog + pricing first):
callCloudApi(service="tcb", action="DescribeManagedAIModelList", params={ EnvId })Returns
ManagedAIModelGroup[]withGroupName,Remark, andModels: [{ Model, EnableMCP, ModelSpec, ModelChargingInfo }]. This is the single source of truth for supported model names and pricing — do not infer them from memory. Use the exactModelstring from here when callingUpdateAIModel.ModelChargingInfoincludes input / output prices and billing unit. Surface the prices to the user before enabling.Then enable (note:
Modelsis a full replacement — always resend the already-enabled models together with the new one):callCloudApi(service="tcb", action="UpdateAIModel", params={ EnvId, GroupName: "cloudbase", Models: [ // resend every model that DescribeAIModels already showed as enabled { Model: "<already-enabled model>" }, // append the newly-requested one, using the exact spelling from DescribeManagedAIModelList { Model: "<target model>" } ], Status: 1 }) -
The requested model is not in the managed catalog (not found by
DescribeManagedAIModelList) → jump to the next section, Custom onboarding (models outside the managed catalog).
All Actions use
service=tcb,Version=2018-06-08. Parameters are PascalCase; fall back to camelCase only onInvalidParameter.
Available Providers and Models
ai.createModel(<GroupName>) accepts exactly three kinds of legal values; ai.createImageModel("hunyuan-image") is the dedicated image-generation entry point.
1. "cloudbase" — the main managed group (recommended)
GroupName: "cloudbase",Type: "builtin",Remark: "腾讯云开发"(Tencent CloudBase)- Backed by Tencent Cloud TokenHub, a unified managed pool covering multiple vendors — Hunyuan (HY 2.0 Instruct, HY 2.0 Think, Hunyuan-role, Hy3 preview, …), DeepSeek (DeepSeek-V4-Pro, DeepSeek-V4-Flash, Deepseek-v3.2, Deepseek-v3.1, Deepseek-r1-0528, Deepseek-v3-0324, …), Zhipu GLM (GLM-5, GLM-5-Turbo, GLM-5.1, GLM-5V-Turbo), Kimi (K2.5, K2.6), MiniMax (M2.5, M2.7), and more. The roster evolves — do not hard-code specific SKUs; discover at runtime
- No model is enabled by default. Always call
DescribeAIModelsfirst to see what the env has actually enabled; if your target model is missing, callDescribeManagedAIModelListfor the authoritative catalog + pricing and thenUpdateAIModel(Status: 1,Modelsfull-replacement) to enable it before making the SDK call. - Authoritative catalog + pricing:
DescribeManagedAIModelList - Env-enabled set:
DescribeAIModels
2. "hunyuan-exp" — legacy builtin group (kept for compatibility)
- Default model:
hunyuan-2.0-instruct-20251111; additional hunyuan SKUs must be discovered at runtime viaDescribeAIModels({ GroupName: "hunyuan-exp" }).Models[]— do not hard-code other IDs - Use it directly only if
DescribeAIModelsactually returns this group withStatus=1. New projects should prefercloudbase
3. User-defined GroupName
- Onboarded via
CreateAIModel(see the next section). The customGroupNameMUST start withcustom-(e.g.custom-kimi,custom-moonshot,custom-openai-compat). This naming convention prevents future collisions with built-in / vendor GroupNames (likecloudbase,hunyuan-exp,deepseek,glm,kimi,minimax) that the platform may introduce over time - Examples:
createModel("custom-kimi"),createModel("custom-openai-compat")
Image generation (independent API)
ai.createImageModel("hunyuan-image")+model: "hunyuan-image". Only supported in the Node SDK
Never write guesses like
createModel("deepseek")orcreateModel("custom")unlessDescribeAIModelsexplicitly returned that exactGroupName.
Custom onboarding (models outside the managed catalog)
When the user wants a non-managed text model (self-hosted, enterprise-internal, third-party OpenAI-compatible endpoint, …), do not block. Guide them through onboarding — console flow, the full CreateAIModel payload, and follow-up management steps: custom-onboarding.md. The custom GroupName MUST start with custom-; custom-model billing is covered by the third-party provider and does not draw from the Token Credits resource pack.
Installation
npm install @cloudbase/node-sdk
⚠️ The AI feature requires version 3.16.0 or above. Check with npm list @cloudbase/node-sdk.
Initialization
Inside a CloudBase cloud function
const tcb = require('@cloudbase/node-sdk');
const app = tcb.init({ env: '<YOUR_ENV_ID>' });
exports.main = async (event, context) => {
const ai = app.ai();
// Use AI features
};
Cloud function configuration for AI models
⚠️ Important: when creating cloud functions that use AI models (especially generateImage() and large text generation), set a longer timeout — these operations can be slow.
Using the MCP tool manageFunctions(action="createFunction"):
Legacy compatibility: if an older prompt still says createFunction, keep the same payload shape but execute it through manageFunctions(action="createFunction").
Set timeout inside the func object:
- Parameter:
func.timeout(number) - Unit: seconds
- Range: 1 – 900
- Default: 20 seconds (usually too short for AI operations)
Recommended timeouts:
- Text generation (
generateText): 60 – 120 s - Streaming (
streamText): 60 – 120 s - Image generation (
generateImage): 300 – 900 s (recommended: 900 s) - Combined operations: 900 s (maximum allowed)
In a regular Node.js server
const tcb = require('@cloudbase/node-sdk');
const app = tcb.init({
env: '<YOUR_ENV_ID>',
secretId: '<YOUR_SECRET_ID>',
secretKey: '<YOUR_SECRET_KEY>'
});
const ai = app.ai();
SDK API Reference (on demand)
For full generateText / streamText / generateImage code examples, the error-handling pattern, image-generation parameters, and the complete TypeScript type definitions, read api-reference.md. That file (together with this SKILL.md) is the authoritative reference for @cloudbase/node-sdk's AI surface — look up method signatures there before writing code. If a method or field is not documented there, stop and ask, or check the live contract via the MCP tools. No guessing.
Best Practices
- Run the two-step preflight before writing business code — ① eligibility:
queryEnv→callCloudApi(tcb, DescribeEnvPostpayPackage)to confirm the Token Credits resource pack (text + image share the same pack); ② group readiness:DescribeAIModelsfor thecloudbasegroup and itsModels[],DescribeManagedAIModelListfor the authoritative supported-model catalog,UpdateAIModelwith a full-replacementModels[]+Status: 1when the target model is missing. If the pack is missing, return the purchase linkhttps://buy.cloud.tencent.com/lowcode?buyType=resPack&envId={envId}&resourceType=tokeninstead of emitting SDK code and letting the user debug runtime errors. - Never assume any model is already enabled — not
deepseek-v4-flash, nothunyuan-image, not anything. Always verify withDescribeAIModelsfirst; if the target is missing, look up the exactModelstring inDescribeManagedAIModelList(do not guess the spelling) and thenUpdateAIModelto enable it. createModelaccepts exactly three kinds of values —"cloudbase"(the main managed group),"hunyuan-exp"(legacy builtin), or a user-defined GroupName registered viaCreateAIModel(MUST start withcustom-, e.g.custom-kimi,custom-openai-compat). Never guess withcreateModel("deepseek")/createModel("kimi")/createModel("custom")— the first two are vendor/model names, the last is a placeholder.createImageModel("hunyuan-image")is a separate image API — keep it as-is.- Do not invent SDK method names or parameters. This skill (SKILL.md +
references/api-reference.md) is the authoritative reference for@cloudbase/node-sdk's AI surface — look up the method signature there before writing code. If a method or field is not documented there, stop and ask, or check the live contract via the MCP tools. No guessing. - Show pricing before enabling a new managed model —
DescribeManagedAIModelListreturnsModelSpec(context length, max input/output tokens) +ModelChargingInfo(input / output / cache prices, billing unit). Show the prices to the user before callingUpdateAIModel. - Plan timeout and quota separately for image generation —
generateImagecosts more per call than text and takes longer. For cloud functions, settimeoutto900s. HTTP-function gateways cap at 60s, so use an async-task + polling pattern. Throttle per-user concurrency and frequency to avoid burning an entire Token pack on one failure. - Prefer streaming for long-form interactions — in HTTP-function or cloud-function SSE scenarios, use
streamText+for await (const chunk of result.textStream)to flush chunks back to the client incrementally. Handle stream interruption incatchand close the underlying response. - Pin
@cloudbase/node-sdk>= 3.16.0 on the server — image generation is only available from this version. Verify withnpm ls @cloudbase/node-sdkto confirm the version actually loaded by the cloud function / cloud run runtime — local and production can drift. - Centralize model names in config, not scattered literals. Keep the chosen text / image model in a single constant and source from
DescribeAIModels/DescribeManagedAIModelList. The managed catalog evolves; a single source of truth makes upgrades cheap. For models outside the managed catalog, follow the Custom Onboarding section — never hard-code third-party API keys in business code (letCreateAIModel.Secret.ApiKeyhold them via CloudBase). - Distinguish "preflight failure" from "model call failure" — the former means the resource pack is not active or the target model has not been enabled via
UpdateAIModel(guide the user to purchase / enable). The latter is a parameter issue or upstream error. Do not wrap both in one generic toast. - Do not log full prompts or generated text in production — log only
usage.total_tokensand a short prefix. Prompts can leak sensitive content; token counts can leak cost signals. - TypeScript: do NOT use
anyto silence SDK type errors. The Node SDK ships its own types; narrow withunknown+ a type guard, write a preciseinterfacefor the shape you consume, or augment types in a local.d.ts. Never: any,as any,@ts-ignore,@ts-nocheck. See the Engineering constitution in theweb-developmentskill — it applies to backend TS too. - Self-verify before claiming done.
tsc --noEmit+ project build + actually invoke the function (local invoke /manageFunctions(action="invokeFunction")/ direct HTTP hit) and confirmusage.total_tokens > 0and the returned text is not an error envelope. "It should work" without a real round-trip is not acceptable evidence.
Reference index
All packaged reference files (required for skill lint reachability):
- api-reference.md — generateText / streamText / generateImage examples, error-handling pattern, image parameters, TypeScript type definitions
- custom-onboarding.md — onboarding models outside the managed catalog (console flow +
CreateAIModel)
Related skills
More from tencentcloudbase/cloudbase-skills and the wider catalog.

ai-model-nodejs
Use this skill for Node.js backend AI via @cloudbase/node-sdk (>=3.16.0) — cloud functions, CloudRun, Express, Koa, NestJS, serverless APIs, scheduled jobs, LLM proxies. Only SDK supporting image generation (ai.createImageModel + generateImage). Text models via ai.createModel with groups cloudbase, hunyuan-exp, or custom-*. Model IDs (deepseek-v4-flash, deepseek-v3.2, hunyuan-2.0-instruct-20251111, glm-5, kimi-k2.6) go in the model field of generateText/streamText. MUST run two-step preflight before code — see body. Keywords: backend, 云函数, 云托管, serverless, LLM proxy, agent orchestration, generateText, streamText, generateImage, createModel, hunyuan-image, Token Credits, TokenHub, Hunyuan, DeepSeek, GLM, Kimi, MiniMax. NOT for browser/Web (use ai-model-web) or Mini Program (use ai-model-wechat).

ai-model-web
Use this skill when a browser/Web app (React, Vue, Angular, Next, Nuxt, static sites, SPAs, dashboards, AI chat UI) needs AI models via @cloudbase/js-sdk. Default routing for page/页面/Web/前端/frontend/网页/H5 AI — call directly from browser, do NOT propose a Node.js proxy. Covers generateText and streamText. Models via ai.createModel with groups cloudbase, hunyuan-exp, or custom-*. Model IDs (deepseek-v4-flash, deepseek-v3.2, hunyuan-2.0-instruct-20251111, glm-5, kimi-k2.6) go in the model field. MUST run two-step preflight before code — see body. Keywords: 页面, Web, 前端, React, Vue, Next, Nuxt, SPA, AI chat UI, generateText, streamText, createModel, hunyuan-exp, Token Credits, TokenHub, Hunyuan, DeepSeek, GLM, Kimi, MiniMax. NOT for Node.js backend (use ai-model-nodejs), Mini Program (use ai-model-wechat), or image generation (Node SDK only).

ai-model-wechat
Use this skill for WeChat Mini Program AI via wx.cloud.extend.AI (小程序, 企业微信小程序, wx.cloud apps). Features generateText and streamText with callbacks (onText, onEvent, onFinish). Models via wx.cloud.extend.AI.createModel with groups hunyuan-exp (小程序成长计划), cloudbase (main managed), or custom-*. Model IDs (deepseek-v4-flash, deepseek-v3.2, hunyuan-2.0-instruct-20251111, glm-5, kimi-k2.6) go in the data wrapper model field. API differs from JS/Node SDK — streamText needs data wrapper, generateText returns raw response. MUST run two-step preflight before code — see body. Keywords: Mini Program AI, wx.cloud.extend.AI, 小程序成长计划, ai_miniprogram_inspire_plan, Token Credits 资源包, generateText, streamText, createModel, hunyuan-exp, TokenHub, Hunyuan, DeepSeek, GLM, Kimi, MiniMax. NOT for browser/Web (use ai-model-web), Node.js backend (use ai-model-nodejs), or image generation (use ai-model-nodejs).

auth-nodejs-cloudbase
CloudBase Node SDK auth guide for server-side identity, user lookup, and custom login tickets. This skill should be used when Node.js code must read caller identity, inspect end users, or bridge an existing user system into CloudBase; not when configuring providers or building client login UI.

auth-tool-cloudbase
CloudBase auth provider configuration and login-readiness guide. This skill should be used when users need to inspect, enable, disable, or configure auth providers, publishable-key prerequisites, login methods, SMS/email sender setup, or other provider-side readiness before implementing a client or backend auth flow.

auth-web-cloudbase
CloudBase Web Authentication Quick Guide for frontend integration after auth-tool has already been checked. Provides concise and practical Web authentication solutions with multiple login methods and complete user management.