Custom Layouts and Pages

If you want to have full control over the layout and logic flow, you can build your own pages using our built-in components or low-level functions.

By default, StackHandler creates all pages you need, however, you can replace them with your own pages.

Simple Example

For example, if you want to create a custom sign-in page with a customized title on the top, you can create a file at app/signin/page.tsx:

app/signin/page.tsx
1import { SignIn } from "@stackframe/stack";
2
3export default function CustomSignInPage() {
4 return (
5 <div>
6 <h1>My Custom Sign In page</h1>
7 <SignIn />
8 </div>
9 );
10}

Then you can instruct the Stack app in stack.ts to use your custom sign in page:

stack.ts
1export const stackServerApp = new StackServerApp({
2 // ...
3 // add these three lines
4 urls: {
5 signIn: '/signin',
6 }
7});

You are now all set! If you visit the /signin page, you should see your custom sign in page. If your user visits a protected page or the old /handler/sign-in URL, they will be redirected to your new sign-in page.

For more examples, please refer to the Examples.

From scratch

We also provide the low-level functions powering our components, so that you can build your own logic. For example, to build a custom OAuth sign-in button, create a file at app/signin/page.tsx:

app/signin/page.tsx
1'use client';
2import { useStackApp } from "@stackframe/stack";
3
4export default function CustomOAuthSignIn() {
5 const app = useStackApp();
6
7 return (
8 <div>
9 <h1>My Custom Sign In page</h1>
10 <button onClick={async () => {
11 // this will redirect to the OAuth provider's login page
12 await app.signInWithOAuth('google');
13 }}>
14 Sign In with Google
15 </button>
16 </div>
17 );
18}

Again, edit the Stack app in stack.ts to use your custom sign in page:

stack.ts
1export const stackServerApp = new StackServerApp({
2 // ...
3 // add these three lines
4 urls: {
5 signIn: '/signin',
6 }
7});

As above, visit the /signin page to see your newly created custom OAuth page.