Skip to content

Commit 4876f0d

Browse files
Move database info to environment variables, work on auth
1 parent 0b4f3e2 commit 4876f0d

File tree

10 files changed

+143
-28
lines changed

10 files changed

+143
-28
lines changed

README.md

+17-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,25 @@ If you trust the workspace on Visual Studio Code, `bun run dev` will automatical
1010

1111
If you want to disable this, press `Ctrl + Shift + P` and type "Tasks: Manage Automatic Tasks", then disable automatic tasks.
1212

13+
## Setting up
14+
15+
1. Set up your [Supabase](https://supabase.com) project using the database specs on `./assets/types/database.ts`.
16+
2. Optional: use triggers and RLS to enforce the database schema.
17+
3. In Project Settings -> API, get your project URL and anonymous key.
18+
4. Create an `.env` file in the root directory of the project with the following content:
19+
```.env
20+
SUPABASE_URL = (your Supabase URL)
21+
SUPABASE_ANON_KEY = (your Supabase anonymous key)
22+
```
23+
5. If you haven't already, install [npm](https://npmjs.com) or any alternatives. (I personally use [Bun](https://bun.sh) for its unparalleled speed, but you can use whatever you want.)
24+
6. Clone this repository. Or click the green "Code" button and download the ZIP file.
25+
26+
If you want to deploy this using Vercel like I am, you should integrate your Supabase project with Vercel so that the environment variables are accessible:
27+
In your Supabase project, go to Settings -> Integrations. It should have a "Vercel Integration" section. The rest should be straightforward.
28+
1329
## Running
1430

1531
Make sure to install the dependencies:
16-
1732
```bash
1833
# if you use npm:
1934
npm install
@@ -24,8 +39,8 @@ yarn install
2439
# if you use bun:
2540
bun install
2641
```
27-
Start the development server on `http://localhost:3000`:
2842

43+
Start the development server on `http://localhost:3000`:
2944
```bash
3045
# if you use npm:
3146
npm run dev

assets/lang/en.ts

+5
Original file line numberDiff line numberDiff line change
@@ -2871,6 +2871,11 @@ We do not expect there to be any cookies used on this site, but just to make sur
28712871
},
28722872
noscriptWarn: "You cannot sign in with JavaScript disabled.",
28732873
alreadySignedIn: "You are already signed in!",
2874+
error: `An error occurred while signing in:
2875+
{error}
2876+
2877+
Press OK to go to GitHub Issues, where you can report this error.
2878+
Press Cancel to return to the homepage.`,
28742879
},
28752880
rules: `md_
28762881
# Site Rules

bun.lockb

753 Bytes
Binary file not shown.

components/header.vue

+17-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script setup lang="ts">
2+
import { useSupabaseUser } from '#imports';
3+
24
const localePath = useLocalePath();
35
4-
function dbg(arg: any): typeof arg {
5-
console.log(arg);
6-
return arg;
7-
}
6+
const { data } = await useSupabaseUser();
7+
const user = data.user;
88
</script>
99

1010
<template>
@@ -13,16 +13,25 @@ function dbg(arg: any): typeof arg {
1313
<h1 v-html="$t('common.appName')"></h1>
1414
</NuxtLink>
1515
<nav>
16-
<NuxtLink :to="localePath('/')" class="hide-no-error"
16+
<NuxtLink
17+
:to="localePath('/')"
18+
class="hide-no-error"
1719
v-thtml="$t('common.nav.home')"
1820
/>
19-
<NuxtLink :to="localePath('/faq')" class="hide-error"
21+
<NuxtLink
22+
:to="localePath('/faq')"
23+
class="hide-error"
2024
v-thtml="$t('common.nav.faq')"
2125
/>
22-
<NuxtLink :to="localePath('/map')" class="hide-error"
26+
<NuxtLink
27+
:to="localePath('/map')"
28+
class="hide-error"
2329
v-thtml="$t('common.nav.map')"
2430
/>
25-
<NuxtLink :to="localePath('/sign-in')" class="hide-noscript hide-error"
31+
<NuxtLink
32+
:to="localePath('/sign-in')"
33+
class="hide-noscript hide-error"
34+
v-show="!user"
2635
v-thtml="$t('common.nav.signIn')"
2736
/>
2837
</nav>

composables/database.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,34 @@
11
import { createClient } from "@supabase/supabase-js";
22
import { DBWrapper } from '~/assets/scripts/database';
33

4+
export const useSupabaseInfo = () => {
5+
if(!process.env.SUPABASE_URL || !process.env.SUPABASE_ANON_KEY) {
6+
throw new Error("Missing Supabase URL or Anon Key");
7+
}
8+
9+
return {
10+
url: process.env.SUPABASE_URL,
11+
key: process.env.SUPABASE_ANON_KEY
12+
}
13+
}
14+
415
/** Creates an instance of the database wrapper. */
516
export const useDatabase = () => {
6-
const runtimeConfig = useRuntimeConfig();
7-
const url = runtimeConfig.public.supabaseUrl;
8-
const key = runtimeConfig.public.supabaseAnonKey;
17+
const { url, key } = useSupabaseInfo();
918

1019
return new DBWrapper(url, key);
1120
};
1221

1322
/** Creates an instance of Supabase. */
1423
export const useSupabase = () => {
15-
const runtimeConfig = useRuntimeConfig();
16-
const url = runtimeConfig.public.supabaseUrl;
17-
const key = runtimeConfig.public.supabaseAnonKey;
24+
const { url, key } = useSupabaseInfo();
1825

1926
return createClient(url, key);
2027
}
2128

2229
/** Creates an instance of Supabase, then get the current user. */
2330
export const useSupabaseUser = () => {
24-
const runtimeConfig = useRuntimeConfig();
25-
const url = runtimeConfig.public.supabaseUrl;
26-
const key = runtimeConfig.public.supabaseAnonKey;
31+
const { url, key } = useSupabaseInfo();
2732

2833
const supabase = createClient(url, key);
2934

layouts/none.vue

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<template><slot/></template>

nuxt.config.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1+
if(!process.env.SUPABASE_URL || !process.env.SUPABASE_ANON_KEY) {
2+
throw new Error(`
3+
Could not find Supabase URL or key in environment variables.
4+
Are you sure you set it up right?
5+
Tip: Check your .env file and refer to the README.`);
6+
}
7+
18
// https://nuxt.com/docs/api/configuration/nuxt-config
29
export default defineNuxtConfig({
310
css: ['~/assets/scss/main.scss'],
411

5-
runtimeConfig: {
6-
public: {
7-
supabaseUrl: 'https://fohgyexhzptaxjqrrrfd.supabase.co',
8-
supabaseAnonKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZvaGd5ZXhoenB0YXhqcXJycmZkIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MDUwMjQxNTcsImV4cCI6MjAyMDYwMDE1N30.fa7XvwiBbWSe2MLIR6Wkh_OC95uV7UXxt7_25PlyAlc'
9-
}
10-
},
11-
1212
app: {
1313
head: {
1414
meta: [

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"dependencies": {
1313
"@nuxt/kit": "^3.12.3",
1414
"@nuxtjs/i18n": "^8.3.1",
15+
"@supabase/ssr": "^0.4.0",
1516
"@supabase/supabase-js": "^2.44.2",
1617
"@types/sanitize-html": "^2.11.0",
1718
"markdown-it": "^14.1.0",

pages/auth/oauth-callback.vue

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<template>
2+
<noscript>
3+
<h1>
4+
{{ $t('signIn.noscriptWarn') }}
5+
</h1>
6+
</noscript>
7+
</template>
8+
9+
<script lang="ts" setup>
10+
const { t } = useI18n();
11+
const localePath = useLocalePath();
12+
const router = useRouter();
13+
const supabase = useSupabase();
14+
15+
function showError(error: Error) {
16+
console.error(error);
17+
18+
// OK (Yes): Go to GitHub Issues
19+
// Cancel (No): Go to homepage
20+
const response = confirm(t('signIn.error', { error: error.message }));
21+
22+
if(response) {
23+
router.push("https://github.com/techmino-hub/techmino-hub-source-code/issues");
24+
} else {
25+
router.push(localePath('/'));
26+
}
27+
}
28+
29+
onMounted(async function() {
30+
const searchParams = new URLSearchParams(window.location.search);
31+
const code = searchParams.get('code');
32+
const next = searchParams.get('next') ?? localePath('/');
33+
const error = searchParams.get('error');
34+
35+
if(error) {
36+
showError(new Error(error));
37+
return;
38+
}
39+
40+
if(!code) {
41+
showError(new Error('Code not found'));
42+
return;
43+
}
44+
45+
const { error: sessionError } =
46+
await supabase.auth.exchangeCodeForSession(code);
47+
48+
if(sessionError) {
49+
showError(sessionError);
50+
return;
51+
}
52+
53+
router.push(next);
54+
});
55+
56+
definePageMeta({ layout: 'none' });
57+
</script>
58+
59+
<style scoped>
60+
h1 {
61+
font-size: 2em;
62+
text-align: center;
63+
margin-top: 1em;
64+
}
65+
</style>

pages/sign-in.vue

+16-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { type Provider } from '@supabase/supabase-js';
2626
import { useSupabase } from '~/composables/database';
2727
2828
const localePath = useLocalePath();
29+
const router = useRouter();
2930
3031
const supabase = useSupabase();
3132
@@ -34,8 +35,21 @@ const user = data.user;
3435
3536
console.debug("user:", user); // DEBUG
3637
37-
function oauth(provider: Provider) {
38-
supabase.auth.signInWithOAuth({ provider });
38+
async function oauth(provider: Provider) {
39+
const { data, error } = await supabase.auth.signInWithOAuth({
40+
provider,
41+
options: {
42+
redirectTo: '/auth/oauth-callback'
43+
}
44+
});
45+
46+
if(data.url) {
47+
router.push(data.url);
48+
}
49+
50+
if(error) {
51+
throw error;
52+
}
3953
}
4054
</script>
4155

0 commit comments

Comments
 (0)