Skip to content

Commit

Permalink
Merge pull request #6 from ergofriend/add-demo-app
Browse files Browse the repository at this point in the history
demo for remix-auth-twitch
  • Loading branch information
ergofriend committed May 19, 2023
2 parents a76399d + e3f09e5 commit e658eeb
Show file tree
Hide file tree
Showing 34 changed files with 8,500 additions and 0 deletions.
3 changes: 3 additions & 0 deletions example/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# .dev.vars
TWITCH_API_CLIENT=
TWITCH_API_SECRET=
4 changes: 4 additions & 0 deletions example/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"],
};
7 changes: 7 additions & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules

/.cache
/functions/\[\[path\]\].js
/functions/\[\[path\]\].js.map
/public/build
.dev.vars
1 change: 1 addition & 0 deletions example/.node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
16.13.0
20 changes: 20 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Demo project for remix-auth-twitch

## Environment variables

```sh
touch .dev.vars

TWITCH_API_CLIENT=xxx
TWITCH_API_SECRET=xxx
```

## Run

```sh
yarn install

yarn dev
```

open http://localhost:3000
34 changes: 34 additions & 0 deletions example/app/components/card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Form } from '@remix-run/react'
import { FC } from 'react'
import { AuthUser } from '~/services/auth.server'

type Props = {
user: AuthUser
}

export const Card: FC<Props> = ({ user }) => {
return (
<div className='w-full max-w-sm bg-gray-700 border border-blue-100 rounded-lg shadow '>
<div className='flex flex-col items-center p-5 gap-2'>
<img
width={80}
height={80}
className='mb-3 rounded-full shadow-lg'
src={user.thumbnail}
alt={user.displayName}
/>
<h5 className='mb-1 text-xl font-medium text-blue-200'>
{user.displayName}
</h5>
<span className='text-sm text-blue-300 '>{user.username}</span>
<Form replace method='post' action='/auth/logout' className='pt-2'>
<button className='relative inline-flex items-center justify-center p-0.5 mb-2 mr-2 overflow-hidden text-sm font-medium text-blue-500 rounded-lg group bg-gradient-to-br from-cyan-500 to-blue-500 group-hover:from-cyan-500 group-hover:to-blue-500 hover:text-white dark:text-white focus:ring-4 focus:outline-none focus:ring-cyan-200 dark:focus:ring-cyan-800'>
<span className='relative px-5 py-2.5 transition-all ease-in duration-75 bg-slate-800 rounded-md group-hover:bg-opacity-0'>
Logout
</span>
</button>
</Form>
</div>
</div>
)
}
13 changes: 13 additions & 0 deletions example/app/components/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { FC, ReactNode } from 'react'

type Props = {
children: ReactNode
}

export const Layout: FC<Props> = ({ children }) => {
return (
<div className='flex flex-col justify-center items-center gap-10 h-full'>
{children}
</div>
)
}
14 changes: 14 additions & 0 deletions example/app/components/login-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Form } from '@remix-run/react'

export const LoginButton = () => {
return (
<Form method='post' action='/auth/twitch'>
<button
type='submit'
className='text-white bg-gradient-to-r from-cyan-500 to-blue-500 hover:bg-gradient-to-bl focus:ring-4 focus:outline-none focus:ring-cyan-300 dark:focus:ring-cyan-800 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2'
>
Login with Twitch
</button>
</Form>
)
}
18 changes: 18 additions & 0 deletions example/app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* By default, Remix will handle hydrating your app on the client for you.
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
* For more information, see https://remix.run/file-conventions/entry.client
*/

import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";

startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
38 changes: 38 additions & 0 deletions example/app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* By default, Remix will handle generating the HTTP Response for you.
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
* For more information, see https://remix.run/file-conventions/entry.server
*/

import type { EntryContext } from "@remix-run/cloudflare";
import { RemixServer } from "@remix-run/react";
import isbot from "isbot";
import { renderToReadableStream } from "react-dom/server";

export default async function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
const body = await renderToReadableStream(
<RemixServer context={remixContext} url={request.url} />,
{
signal: request.signal,
onError(error: unknown) {
console.error(error);
responseStatusCode = 500;
},
}
);

if (isbot(request.headers.get("user-agent"))) {
await body.allReady;
}

responseHeaders.set("Content-Type", "text/html");
return new Response(body, {
headers: responseHeaders,
status: responseStatusCode,
});
}
19 changes: 19 additions & 0 deletions example/app/root.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
--blue-50: 239 246 255;
--blue-100: 219 234 254;
--blue-200: 191 219 254;
--blue-300: 147 197 253;
--blue-400: 96 165 250;
--blue-500: 59 130 246;
--blue-600: 37 99 235;
--blue-700: 29 78 216;
--blue-800: 30 64 175;
--blue-900: 30 58 138;
--blue-950: 23 37 84;
--gray-700: 55 65 81;
--slate-800: 30 41 59;
}
36 changes: 36 additions & 0 deletions example/app/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { LinksFunction } from '@remix-run/cloudflare'
import { cssBundleHref } from '@remix-run/css-bundle'
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from '@remix-run/react'

import styles from './root.css'

export const links: LinksFunction = () => [
...(cssBundleHref ? [{ rel: 'stylesheet', href: cssBundleHref }] : []),
{ rel: 'stylesheet', href: styles },
]

export default function App() {
return (
<html lang='en' className='bg-slate-800 h-full'>
<head>
<meta charSet='utf-8' />
<meta name='viewport' content='width=device-width,initial-scale=1' />
<Meta />
<Links />
</head>
<body className='h-full'>
<Outlet />
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
)
}
45 changes: 45 additions & 0 deletions example/app/routes/__layout._index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { V2_MetaFunction } from '@remix-run/cloudflare'
import { Link } from '@remix-run/react'

import { Layout } from '~/components/layout'

export const meta: V2_MetaFunction = () => {
return [{ title: 'Remix Auth Twitch Demo' }]
}

export default function Page() {
return (
<Layout>
<h1 className='text-blue-400 text-4xl'>Remix Auth Twitch Demo</h1>

<ul className='max-w-md space-y-1 text-blue-200 list-disc list-inside'>
<li>
<Link
className='text-blue-200 underline'
to='https://github.com/sergiodxa/remix-auth'
>
sergiodxa/remix-auth: Simple Authentication for Remix
</Link>
</li>
<li>
<Link
className='text-blue-200 underline'
to='https://github.com/ergofriend/remix-auth-twitch'
>
ergofriend/remix-auth-twitch: Remix Auth Plugin for Twitch
</Link>
</li>
</ul>

<p className='text-blue-300'>
You can remove the link to this application at{' '}
<Link
className='text-blue-200 underline'
to={'https://www.twitch.tv/settings/connections'}
>
https://www.twitch.tv/settings/connections
</Link>
</p>
</Layout>
)
}
12 changes: 12 additions & 0 deletions example/app/routes/__layout.failure.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Layout } from '~/components/layout'
import { LoginButton } from '~/components/login-button'

export default function LoginFailure() {
return (
<Layout>
<h2 className='text-red-400 text-2xl'>Login Failure</h2>
<p className='text-blue-400'>Login failed. Please try again.</p>
<LoginButton />
</Layout>
)
}
10 changes: 10 additions & 0 deletions example/app/routes/__layout.login.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Layout } from '~/components/layout'
import { LoginButton } from '~/components/login-button'

export default function Page() {
return (
<Layout>
<LoginButton />
</Layout>
)
}
22 changes: 22 additions & 0 deletions example/app/routes/__layout.secret.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { LoaderFunction, redirect } from '@remix-run/cloudflare'
import { useLoaderData } from '@remix-run/react'

import { Card } from '~/components/card'
import { Layout } from '~/components/layout'
import { authenticator } from '~/services/auth.server'

export const loader: LoaderFunction = async ({ request }) => {
const user = await authenticator.isAuthenticated(request)
if (!user) return redirect('/login')
return { user }
}

export default function Page() {
const { user } = useLoaderData<typeof loader>()

return (
<Layout>
<Card user={user} />
</Layout>
)
}
35 changes: 35 additions & 0 deletions example/app/routes/__layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { NavLink, Outlet } from '@remix-run/react'

export default function Page() {
return (
<div className='grid grid-rows-[auto_1fr] min-h-full p-4'>
<div className='flex gap-4'>
<NavLink
to='/'
className='text-blue-200 underline [&.active]:text-blue-400'
>
Home
</NavLink>
<NavLink
to='/login'
className='text-blue-200 underline [&.active]:text-blue-400'
>
Login
</NavLink>
<NavLink
to='/failure'
className='text-blue-200 underline [&.active]:text-blue-400'
>
Failure
</NavLink>
<NavLink
to='/secret'
className='text-blue-200 underline [&.active]:text-blue-400'
>
Secret
</NavLink>
</div>
<Outlet />
</div>
)
}
7 changes: 7 additions & 0 deletions example/app/routes/auth.logout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { ActionFunction } from '@remix-run/cloudflare'

import { authenticator } from '~/services/auth.server'

export let action: ActionFunction = async ({ request }) => {
return await authenticator.logout(request, { redirectTo: '/' })
}
10 changes: 10 additions & 0 deletions example/app/routes/auth.twitch.callback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type {LoaderFunction} from '@remix-run/cloudflare'

import {authenticator} from '~/services/auth.server'

export let loader: LoaderFunction = async ({request}) => {
return await authenticator.authenticate('twitch', request, {
successRedirect: '/secret',
failureRedirect: '/failure',
})
}
10 changes: 10 additions & 0 deletions example/app/routes/auth.twitch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type {ActionFunction} from '@remix-run/cloudflare'

import {authenticator} from '~/services/auth.server'

export let action: ActionFunction = async ({request}) => {
return await authenticator.authenticate('twitch', request, {
successRedirect: '/secret',
failureRedirect: '/failure',
})
}
Loading

0 comments on commit e658eeb

Please sign in to comment.