[Docs][Content] Github install, UI changes, platform selection (#1098)

## Summary

This PR improves the documentation for GitHub authentication setup and
self-hosting.

## Changes

### GitHub OAuth/App Setup Guide
- Updated
[github.mdx](cci:7://file:///Users/madison/source/stack-auth/docs/content/docs/%28guides%29/concepts/auth-providers/github.mdx:0:0-0:0)
with clearer instructions differentiating between **GitHub OAuth App**
and **GitHub App** setup
- Added better explanations for when to use each option

### Self-Hosting Documentation
- Added prominent danger warning about self-hosting responsibilities
- Migrated inline shell commands to structured code examples using
[PlatformCodeblock](cci:1://file:///Users/madison/source/stack-auth/docs/src/components/mdx/platform-codeblock.tsx:242:0-673:1)
component
- Created
[docs/code-examples/self-host.ts](cci:7://file:///Users/madison/source/stack-auth/docs/code-examples/self-host.ts:0:0-0:0)
with all self-hosting commands

### Info Component
- Added new `danger` type for critical warnings with red accent styling
- Updated component styling with modern left accent bar and gradient
backgrounds

### PlatformCodeblock Component
- Added `hidePlatformSelector` prop to hide platform dropdown for
single-platform code examples
- Added Shell platform support for terminal commands (Docker, Git, pnpm)
- Filtered Shell platform from user-selectable options in both the
codeblock and header selectors

### Platform Config
- Added Shell platform with Docker, Git, and pnpm frameworks

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added comprehensive self-hosting and authentication customization
example collections for copy-paste use.
  * New "danger" info style with visual accent for important warnings.

* **Documentation**
* GitHub integration guide now centers on GitHub App with an alternate
OAuth path retained.
* Replaced many inline snippets with platform-driven code blocks and
improved platform/framework selector behavior (single-platform
optimization; option to hide selector).
  * Pages now surface "Last updated" above descriptions.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Madison
2026-01-20 11:49:08 -06:00
committed by GitHub
parent 4d42f9aa66
commit d0173af691
12 changed files with 526 additions and 307 deletions
+207
View File
@@ -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 protected]" 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 protected]" 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 protected]" 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[],
},
};
+4 -3
View File
@@ -1,6 +1,8 @@
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';
@@ -8,9 +10,8 @@ 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 {
+106
View File
@@ -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 [email protected]: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[],
}
};