Skip to content

Instantly share code, notes, and snippets.

@maiah
Last active July 14, 2026 23:35
Show Gist options
  • Select an option

  • Save maiah/c8d03b0b89120a100f603b2feb46e22c to your computer and use it in GitHub Desktop.

Select an option

Save maiah/c8d03b0b89120a100f603b2feb46e22c to your computer and use it in GitHub Desktop.
Astro Create Route for Client routing
import type { z } from "astro/zod";
type ExtractParams<T extends string> =
T extends `${string}[${infer Param}]${infer Rest}`
? { [K in Param | keyof ExtractParams<Rest>]: string }
: {};
type IsEmptyObject<T> = keyof T extends never ? true : false;
type HrefArgs<T extends string, S extends z.ZodTypeAny | undefined> =
IsEmptyObject<ExtractParams<T>> extends true
? S extends z.ZodTypeAny
? { searchParams: z.infer<S> }
: void
: S extends z.ZodTypeAny
? { params: ExtractParams<T>; searchParams: z.infer<S> }
: { params: ExtractParams<T> };
type RouteConfig<T extends string, S extends z.ZodTypeAny | undefined> = {
path: T;
searchParams?: S;
};
export function createRoute<
T extends string,
S extends z.ZodTypeAny | undefined = undefined,
>(config: RouteConfig<T, S>) {
return {
getCachePath(): string {
return config.path;
},
getParams(): ExtractParams<T> {
const patternSegments = config.path.split("/");
const pathSegments = window.location.pathname.split("/");
const params: Record<string, string> = {};
for (let i = 0; i < patternSegments.length; i++) {
const seg = patternSegments[i];
const match = seg.match(/^\[(.+)\]$/);
if (match) {
params[match[1]] = pathSegments[i] ?? "";
}
}
return params as ExtractParams<T>;
},
href(
...args: HrefArgs<T, S> extends void ? [] : [args: HrefArgs<T, S>]
): string {
const hrefArgs = args[0] as
| {
params?: Record<string, string>;
searchParams?: Record<string, string>;
}
| undefined;
let url = config.path.replace(
/\[([^\]]+)\]/g,
(_, key: string) => hrefArgs?.params?.[key] ?? "",
);
if (hrefArgs && "searchParams" in hrefArgs && hrefArgs.searchParams) {
const qs = new URLSearchParams(
hrefArgs.searchParams as Record<string, string>,
);
url += `?${qs.toString()}`;
}
return url;
},
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment