# Custom Username Namespaces - Lens Source: https://lens.xyz/docs/protocol/usernames/custom-namespaces Kiwi News: https://news.kiwistand.com/stories/Custom-Username-Namespaces-Lens?index=0x68764660f9ef377a631cdfd93ab1f01f06fec9c7b87f78e5d66fac855294bc15359c8385 Submitted by pedrovilela.eth on 2025-07-15 UTC, 7 upvotes, 0 comments ## Summary This guide explains how Builders can create and manage Custom Username Namespaces, which are app- or group-specific namespaces that can govern username issuance, monetization and more through Username Rules. To create one, a Builder constructs and uploads a Namespace Metadata object, then deploys a Lens Namespace smart contract with the createUsernameNamespace action. The guide also covers fetching a namespace by address or transaction hash with fetchNamespace, searching namespaces with fetchNamespaces, and access control, where the Owner can transfer ownership and Administrators can update metadata, rules and extra data. ## Article Create a Custom Namespace Create Namespace Metadata Upload Namespace Metadata Deploy Namespace Contract Handle Result Fetch New Namespace Fetch a Namespace Search Namespaces Access Control This guide explains custom Username Namespaces and how to create and manage them. As mentioned in the Username concept page, there are two Namespace groups: The Global Namespace: The familiar lens/* namespace. Custom Namespace: App or group-specific namespaces that can govern issuance, monetization, and more by means of Username Rules. Create a Custom Namespace To create a custom Namespace, follow these steps. You MUST be authenticated as Builder to create a custom Namespace. First, construct a Namespace Metadata object with the necessary content. TS/JS JSON Schema Use the @lens-protocol/metadata package to construct a valid NamespaceMetadata object: import { namespace } from "@lens-protocol/metadata"; const metadata = namespace({ description: "A collection of usernames", collection: { name: "Lens Usernames", description: "The official lens/ usernames", },}); Since usernames are ERC-721 tokens, you can also specify EIP-7572 contract-level metadata which makes it easier to trade and display usernames in wallets and marketplaces. Next, upload the Namespace Metadata object to a public URI. import { storageClient } from "./storage-client"; const { uri } = await storageClient.uploadAsJson(metadata); console.log(uri); // e.g., lens://4f91ca… Next, deploy a Lens Namespace smart contract. TypeScript GraphQL React Use the createUsernameNamespace action to deploy the contract. import { evmAddress, uri, RulesSubject } from "@lens-protocol/client";import { createUsernameNamespace } from "@lens-protocol/client/actions"; const result = await createUsernameNamespace(sessionClient, { symbol: "FOO", name: "LensUsernames", namespace: "foo", // foo/ metadataUri: uri("lens://4f91ca…"), rules: { required: [ { usernameLengthRule: { maxLength: 10, minLength: 3, }, }, ], }, rulesSubject: RulesSubject.Account, // default}); To learn more about how to use Username Rules, see the Username Rules guide. TypeScript GraphQL React Next, handle the result using the adapter for the library of your choice and wait for it to be indexed. import { handleOperationWith } from "@lens-protocol/client/viem"; // … const result = await createUsernameNamespace(sessionClient, { symbol: "FOO", namespace: "foo", metadataUri: uri("lens://4f91ca…"),}) .andThen(handleOperationWith(walletClient)) .andThen(sessionClient.waitForTransaction); See the Transaction Lifecycle guide for more information on how to determine the status of the transaction. TypeScript GraphQL Finally, fetch the newly created Namespace using the fetchNamespace action. import { fetchNamespace } from "@lens-protocol/client/actions"; // … const result = await createUsernameNamespace(sessionClient, { symbol: "FOO", namespace: "foo", metadataUri: uri("lens://4f91ca…"),}) .andThen(handleOperationWith(walletClientOrSigner)) .andThen(sessionClient.waitForTransaction) .andThen((txHash) => fetchNamespace(sessionClient, { txHash })); if (result.isErr()) { return console.error(result.error);} // namespace: UsernameNamespace | nullconst namespace = result.value; That's it—you now know how to create and manage Custom Username Namespaces, allowing you to build app- or group-specific namespaces. Fetch a Namespace TypeScript GraphQL React Use the fetchNamespace action to fetch a single Namespace by address or by transaction hash. import { evmAddress } from "@lens-protocol/client";import { fetchNamespace } from "@lens-protocol/client/actions";import { client } from "./client"; const result = await fetchNamespace(client, { namespace: evmAddress("0x1234…"),}); if (result.isErr()) { return console.error(result.error);} const namespace = result.value; Search Namespaces TypeScript GraphQL React Use the paginated fetchNamespaces action to search for namespaces. import { fetchNamespaces } from "@lens-protocol/client/actions"; import { client } from "./client"; const result = await fetchNamespaces(client, { filter: { searchBy: "name", },}); if (result.isErr()) { return console.error(result.error);} // items: Arrayconst { items, pageInfo } = result.value; Continue with the Pagination guide for more information on how to handle paginated results. Access Control The Namespace contract supports two roles: Owner and Administrator. Administrators can: Update the Namespace Metadata Update the Namespace Rules Update the Namespace Extra Data The Owner can do everything the administrators can do, plus transfer ownership of the Namespace to another address. See the Team Management guide for more information on how to manage these roles.