Link to a screen in your app
Declare your screens once, then send links that open the right screen in the app or on the web, invite people, and revoke a link.
Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.
Stability The promise an interface ships with.
- Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
- Beta Usable in production; may change before it becomes stable.
- Experimental May change or go away; needs an explicit opt-in in main.yaml.
You will declare one screen, make a link to it, resolve it and revoke it. It takes about 15 minutes. Every link is a getqr.id share, so it expires and shows nothing of the screen or its params.
You need
- A MainSDK app with
shareworking (see share anything).
1. Declare the screens
links:
base: https://app.example.com
routes:
order: { web: /orders/:id, app: orders/:id, params: [id] }2. Make a link
import { links } from "mainsdk";
export async function orderLink(orderId: string) {
const link = await links.create({ screen: "order", params: { id: orderId } }, { expiresIn: "14d" });
return link.url;
}A screen you did not declare, or different params, fail with MAIN-LINK-0002.
3. Resolve an incoming link
import { links } from "mainsdk";
export async function GET(req: Request) {
const target = await links.resolve(new URL(req.url).searchParams.get("u") ?? "");
return Response.json(target); // { kind, route, valid, reason? }
}resolve never throws for an unknown URL. valid is false with reason expired, revoked, used-up or unknown.
4. Invite someone
import { links } from "mainsdk";
export async function inviteJane(id: string) {
return links.invite(
{ screen: "list", params: { id } },
{ email: "jane@example.com", uses: 1, expiresIn: "7d" },
);
}The person accepts with links.accept(req, token) after signing in.
5. Revoke
import { links } from "mainsdk";
export async function revoke(id: string) {
await links.revoke(id);
}Check it worked
import { it } from "node:test";
import assert from "node:assert/strict";
import { createTestApp } from "@mainsdk/testing";
import { links } from "mainsdk";
it("links AC3 reports a revoked link", async () => {
createTestApp({ main: "./main.yaml" });
const link = await links.create({ screen: "order", params: { id: "ord_1" } });
await links.revoke(link.id);
assert.partialDeepStrictEqual(await links.resolve(link.url), { valid: false, reason: "revoked" });
});Troubleshooting
MAIN-LINK-0001(410): the invite is used up, expired, revoked or for another email.MAIN-LINK-0003: a route param identifies a person, such asemail. Pass a record id instead.MAIN-LINK-0004:links.appsis missing what the association files need, orlinks.baseis not HTTPS.
See the links interface.
Was this page helpful?