stack icon indicating copy to clipboard operation
stack copied to clipboard

Customize deep link team URL

Open widavies opened this issue 8 months ago • 1 comments

It'd be awesome if there was a way to customize the deep link team URL

Instead of:

/teams/4762ce00-13e3-4be5-9b40-bc35fcaedcb1

This:

/teams/acme

widavies avatar Apr 26 '25 02:04 widavies

@fomalhautb I would like to put together a PR for this if you are okay with it.

Users could pick between the existing /uuid ("/teams/c058811c-b4d3-4fd4-960f-a9a6a61752b5") method or a custom /team-slug ("/teams/acme") method.

Proposal for the /team-slug method

Backend modifications

Modify the Team model:

model Team {
  // ...
  slug          String?         @unique
}

Valid slugs are lowercase, start with an alphanumeric character, are followed by dashes or more alphanumeric characters, and end with an alphanumeric character.

Slugs could be set while creating a team:

const team = await user.createTeam({
  displayName: 'Stack-Auth Inc.',
  slug: 'stack'
});

or, set by updating the team:

await team.update({
  slug: 'stack-auth'
});

Crucially, these must updates must be atomic & unique - so createTeam(..)/updateTeam(..) should throw an error if another team already exists with a given slug. I believe this will be handled by Postgres automatically.

Usage

Usage would be similar to your deep link example:

"use client";

import { useUser, SelectedTeamSwitcher } from "@stackframe/stack";

export default function TeamPage({ params }: { params: { teamSlug: string } }) {
  const user = useUser({ or: 'redirect' });
  const team = user.useTeamBySlug(params.teamSlug);
  if (!team) {
    return <div>Team not found</div>;
  }
  return (
    <div>
      <SelectedTeamSwitcher 
        urlMap={team => `/team/${team.slug}`} 
        selectedTeam={team}
      />
      
      <p>Team Name: {team.displayName}</p>
      <p>You are a member of this team.</p>
    </div>
  );
}

Other notes

Resolving a team slug to a team id shouldn't require authentication.

For example, I'm building a CRM that allows teams to publish events, like /my-company/my-event/sign-up, where my-company is the team slug. This event sign up is publicly accessible - so visitors won't have a user account - this means that user.useTeamBySlug wouldn't work. We probably need an API for this, something like:

const app = useStackApp();
// User does not have to be on the team, or be signed in at all. Notice that ONLY the teamId should be returned.
string teamId = app.useTeamBySlug('my-company');
// User must be signed in & on the team
const team = user.useTeamBySlug(params.teamSlug);

Then, we leave it up to the programmer to decide whether to restrict the page how they see fit.

widavies avatar Apr 27 '25 20:04 widavies