Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 207 additions & 0 deletions docs/code-examples/customization.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import { CodeExample } from '../lib/code-examples';

export const customizationExamples = {
'sign-in': {
'default': [
{
language: 'JavaScript',
framework: 'Next.js',
code: `'use client';
import { SignIn } from "@stackframe/stack";

export default function DefaultSignIn() {
// optionally redirect to some other page if the user is already signed in
// const user = useUser();
// if (user) { redirect to some other page }
return <SignIn fullPage />;
}`,
highlightLanguage: 'tsx',
filename: 'app/handler/sign-in/page.tsx',
},
] as CodeExample[],

'custom-oauth': [
{
language: 'JavaScript',
framework: 'Next.js',
code: `'use client';
import { useStackApp } from "@stackframe/stack";

export default function CustomOAuthSignIn() {
const app = useStackApp();

return (
<div>
<h1>My Custom Sign In page</h1>
<button onClick={async () => {
// This will redirect to the OAuth provider's login page.
await app.signInWithOAuth('google');
}}>
Sign In with Google
</button>
</div>
);
}`,
highlightLanguage: 'tsx',
filename: 'app/handler/sign-in/page.tsx',
},
] as CodeExample[],

'custom-credential': [
{
language: 'JavaScript',
framework: 'Next.js',
code: `'use client';
import { useStackApp } from "@stackframe/stack";
import { useState } from "react";

export default function CustomCredentialSignIn() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const app = useStackApp();

const onSubmit = async () => {
if (!password) {
setError('Please enter your password');
return;
}
// This will redirect to app.urls.afterSignIn if successful.
// You can customize the redirect URL in the StackServerApp constructor.
const result = await app.signInWithCredential({ email, password });
// It's better to handle each error code separately, but for simplicity,
// we'll just display the error message directly here.
if (result.status === 'error') {
setError(result.error.message);
}
};

return (
<form onSubmit={(e) => { e.preventDefault(); onSubmit(); } }>
{error}
<input type='email' placeholder="email@example.com" value={email} onChange={(e) => setEmail(e.target.value)} />
<input type='password' placeholder="password" value={password} onChange={(e) => setPassword(e.target.value)} />
<button type='submit'>Sign In</button>
</form>
);
}`,
highlightLanguage: 'tsx',
filename: 'app/handler/sign-in/page.tsx',
},
] as CodeExample[],

'custom-magic-link': [
{
language: 'JavaScript',
framework: 'Next.js',
code: `'use client';

import { useStackApp } from "@stackframe/stack";
import { useState } from "react";

export default function CustomMagicLinkSignIn() {
const [email, setEmail] = useState('');
const [error, setError] = useState('');
const [message, setMessage] = useState('');
const app = useStackApp();

const onSubmit = async () => {
if (!email) {
setError('Please enter your email address');
return;
}

// This will send a magic link email to the user's email address.
// When they click the link, they will be redirected to your application.
const result = await app.sendMagicLinkEmail(email);
// It's better to handle each error code separately, but for simplicity,
// we'll just display the error message directly here.
if (result.status === 'error') {
setError(result.error.message);
} else {
setMessage('Magic link sent! Please check your email.');
}
};

return (
<form onSubmit={(e) => { e.preventDefault(); onSubmit(); } }>
{error}
{message ?
<div>{message}</div> :
<>
<input type='email' placeholder="email@example.com" value={email} onChange={(e) => setEmail(e.target.value)} />
<button type='submit'>Send Magic Link</button>
</>}
</form>
);
}`,
highlightLanguage: 'tsx',
filename: 'app/handler/sign-in/page.tsx',
},
] as CodeExample[],
},

'sign-up': {
'default': [
{
language: 'JavaScript',
framework: 'Next.js',
code: `'use client';
import { SignUp } from "@stackframe/stack";

export default function DefaultSignUp() {
// optionally redirect to some other page if the user is already signed in
// const user = useUser();
// if (user) { redirect to some other page }
return <SignUp fullPage />;
}`,
highlightLanguage: 'tsx',
filename: 'app/handler/sign-up/page.tsx',
},
] as CodeExample[],

'custom-credential': [
{
language: 'JavaScript',
framework: 'Next.js',
code: `'use client';

import { useStackApp } from "@stackframe/stack";
import { useState } from "react";

export default function CustomCredentialSignUp() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const app = useStackApp();

const onSubmit = async () => {
if (!password) {
setError('Please enter your password');
return;
}
// This will redirect to app.urls.afterSignUp if successful.
// You can customize the redirect URL in the StackServerApp constructor.
const result = await app.signUpWithCredential({ email, password });
// It's better to handle each error code separately, but for simplicity,
// we'll just display the error message directly here.
if (result.status === 'error') {
setError(result.error.message);
}
};

return (
<form onSubmit={(e) => { e.preventDefault(); onSubmit(); } }>
{error}
<input type='email' placeholder="email@example.com" value={email} onChange={(e) => setEmail(e.target.value)} />
<input type='password' placeholder="password" value={password} onChange={(e) => setPassword(e.target.value)} />
<button type='submit'>Sign Up</button>
</form>
);
}`,
highlightLanguage: 'tsx',
filename: 'app/handler/sign-up/page.tsx',
},
] as CodeExample[],
},
};
7 changes: 4 additions & 3 deletions docs/code-examples/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { CodeExample } from '../lib/code-examples';
import { apiKeysExamples } from './api-keys';
import { customizationExamples } from './customization';
import { paymentsExamples } from './payments';
import { selfHostExamples } from './self-host';
import { setupExamples } from './setup';
import { viteExamples } from './vite-example';

const allExamples: Record<string, Record<string, Record<string, CodeExample[]>>> = {
'setup': setupExamples,
'apps': {...apiKeysExamples, ...paymentsExamples },
'getting-started': viteExamples,
// Add more sections here as needed:
// 'auth': authExamples,
// 'customization': customizationExamples,
'others': selfHostExamples,
'customization': customizationExamples,
};

export function getExample(documentPath: string, exampleName: string): CodeExample[] | undefined {
Expand Down
106 changes: 106 additions & 0 deletions docs/code-examples/self-host.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { CodeExample } from '../lib/code-examples';

export const selfHostExamples = {
'self-host': {
'docker-postgres': [
{
language: 'Shell',
framework: 'Docker',
code: `docker run -d --name db -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=password -e POSTGRES_DB=stackframe -p 5432:5432 postgres:latest`,
highlightLanguage: 'bash',
filename: 'Terminal'
}
] as CodeExample[],

'docker-run': [
{
language: 'Shell',
framework: 'Docker',
code: `docker run --env-file <your-env-file.env> -p 8101:8101 -p 8102:8102 stackauth/server:latest`,
highlightLanguage: 'bash',
filename: 'Terminal'
}
] as CodeExample[],

'git-clone': [
{
language: 'Shell',
framework: 'Git',
code: `git clone git@github.com:stack-auth/stack-auth.git
cd stack-auth`,
highlightLanguage: 'bash',
filename: 'Terminal'
}
] as CodeExample[],

'local-dev-setup': [
{
language: 'Shell',
framework: 'pnpm',
code: `pnpm install

# Run build to build everything once
pnpm run build:dev

# reset & start the dependencies (DB, Inbucket, etc.) as Docker containers, seeding the DB with the Prisma schema
pnpm run start-deps
# pnpm run restart-deps
# pnpm run stop-deps

# Start the dev server
pnpm run dev
# For systems with limited resources, you can run a minimal development setup with just the backend and dashboard
# pnpm run dev:basic

# In a different terminal, run tests in watch mode
pnpm run test`,
highlightLanguage: 'bash',
filename: 'Terminal'
}
] as CodeExample[],

'prisma-studio': [
{
language: 'Shell',
framework: 'pnpm',
code: `pnpm run prisma studio`,
highlightLanguage: 'bash',
filename: 'Terminal'
}
] as CodeExample[],

'backend-build': [
{
language: 'Shell',
framework: 'pnpm',
code: `pnpm install
pnpm build:backend
pnpm start:backend`,
highlightLanguage: 'bash',
filename: 'Terminal'
}
] as CodeExample[],

'dashboard-build': [
{
language: 'Shell',
framework: 'pnpm',
code: `pnpm install
pnpm build:dashboard
pnpm start:dashboard`,
highlightLanguage: 'bash',
filename: 'Terminal'
}
] as CodeExample[],

'db-init': [
{
language: 'Shell',
framework: 'pnpm',
code: `pnpm db:init`,
highlightLanguage: 'bash',
filename: 'Terminal'
}
] as CodeExample[],
}
};
37 changes: 35 additions & 2 deletions docs/content/docs/(guides)/concepts/auth-providers/github.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
---
title: "GitHub"
lastModified: "2026-01-13"
---

This guide explains how to set up GitHub as an authentication provider with Stack Auth. GitHub OAuth allows users to sign in to your application using their GitHub account.
This guide explains how to set up GitHub as an authentication provider with Stack Auth. GitHub allows users to sign in to your Stack Auth-enabled app using their GitHub account.

<Info>
For Development purposes, Stack Auth uses shared keys for this provider. Shared keys are automatically created by Stack, but show Stack's logo on the OAuth sign-in page.
Expand All @@ -11,9 +12,40 @@ You should replace these before you go into production.

## Integration Steps

<Info>
If you are unsure if you need to create a GitHub App, or a GitHub OAuth App, check the [Differences On GitHub](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/differences-between-github-apps-and-oauth-apps).
More than likely, you will want to create a GitHub App. The installation process is the same for both.
</Info>


<Steps>
<Step>
### Create a GitHub OAuth App
### Create a GitHub App

1. Navigate to your [GitHub Developer App Settings](https://github.com/settings/apps).
2. Click the **New GitHub App** button.
3. Enter a name for your application, homepage URL, and a description.
4. For **Authorization callback URL**, add `https://api.stack-auth.com/api/v1/auth/oauth/callback/github`
5. For permissions, at a **minimum**, you will need **Account Permissions > Email Addresses** set to **Read Only**. Your sign-in flow will not work without this permission.
6. Select **Any Account** under the **_Where can this GitHub App be installed_** section.
7. Click **Create GitHub App**
8. Save the **Client ID** and click **Generate a new client secret** to create your **Client Secret**.
</Step>

<Step>
### Enable GitHub Provider in Stack Auth

1. On the Stack Auth dashboard, select **Auth Methods** in the left sidebar.
2. Click **Add SSO Providers** and select **GitHub** as the provider.
3. Set the **Client ID** and **Client Secret** you obtained from your GitHub App earlier.
</Step>
</Steps>

---
<Accordion title="GitHub OAuth App installation">
<Steps>
<Step>
### Create an OAuth App

1. Navigate to your [GitHub Developer Settings](https://github.com/settings/developers).
2. Click the **New OAuth App** button.
Expand All @@ -31,6 +63,7 @@ You should replace these before you go into production.
3. Set the **Client ID** and **Client Secret** you obtained from GitHub earlier.
</Step>
</Steps>
</Accordion>

### Need More Help?

Expand Down
Loading
Loading