Merge pull request #24 from ClicksMinutePer/dependabot/npm_and_yarn/next-12.1.0

diff --git a/.eslintrc.json b/.eslintrc.json
index f0f3abe..c9aa306 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,6 +1,7 @@
 {
   "extends": "next/core-web-vitals",
   "rules": {
-    "@next/next/no-img-element": "off"
+    "@next/next/no-img-element": "off",
+    "@next/next/no-html-link-for-pages": "off"
   }
 }
diff --git a/Components/NavBar.js b/Components/NavBar.js
index 89c8fab..a9e5dbb 100644
--- a/Components/NavBar.js
+++ b/Components/NavBar.js
@@ -37,4 +37,4 @@
 	}
 }
 
-export default NavBar;
\ No newline at end of file
+export default NavBar;
diff --git a/pages/01189998819991197253.js b/pages/01189998819991197253.js
new file mode 100644
index 0000000..7421556
--- /dev/null
+++ b/pages/01189998819991197253.js
@@ -0,0 +1,23 @@
+import Header from '../Components/Header'
+
+export default function Error() {
+	return (
+		<>
+			<Header
+				name="0118 999 881 999 119 7253"
+				subtext={<>
+					Dear Sir/Madam,<br />
+					Fire! Fire! Help me!<br />
+					123 Cavendon Road.<br />
+					Looking forward to hearing from you,<br />
+					All the best, Maurice Moss
+				</>}
+				embedDescription="This is the internet"
+				gradient={["F27878", "D96B6B"]}
+				wave="web/waves/header/rsm"
+				buttons={[{color: "F27878", buttonText: "ffffff", text: "No that's too formal", link: "/#"}]}
+				fullscreen={true}
+			/>
+		</>
+	)
+}
diff --git a/pages/api/nucleus/verify/complete.js b/pages/api/nucleus/verify/complete.js
new file mode 100644
index 0000000..1b58a04
--- /dev/null
+++ b/pages/api/nucleus/verify/complete.js
@@ -0,0 +1,22 @@
+import Axios from 'axios';
+import qs from 'querystring';
+
+const Complete = async (req, res) => {
+    const chk = await Axios.post('http://localhost:3000/api/nucleus/verify/verifyToken', qs.stringify({
+        tkn: req.body.tkn
+    }))
+    if ( !chk.data.success ) {
+        return res.status(200).send({success: false})
+    }
+    let secret = "slwu0rZV5W6WdmGtgI16du8Ar2tQGMr3Q9dE6u3poKiVODNV9SweaA3buawgkTmTuITXDWOUpBcTFA0qWrUvoshi1JB180WOFwA7"
+    try {
+        await Axios.post(`http://192.168.0.18:10000/verify/${req.body.code}`, {
+            secret: secret
+        });
+    } catch (e) {
+        return res.status(200).send({success: false})
+    }
+    return res.status(200).send({success: true});
+}
+
+export default Complete;
\ No newline at end of file
diff --git a/pages/api/nucleus/verify/fetch.js b/pages/api/nucleus/verify/fetch.js
new file mode 100644
index 0000000..ba7aa04
--- /dev/null
+++ b/pages/api/nucleus/verify/fetch.js
@@ -0,0 +1,22 @@
+import Axios from 'axios';
+
+const Validate = async (req, res) => {
+    try {
+        // var out = await Axios.get(`http://192.168.102.7:10000/verify/${req.body.code}`)
+        // out = out.data
+        // let props = {
+        //     user: out.user,
+        //     role: out.role,
+        //     role_name: out.role_name,
+        //     guild: out.guild,
+        //     guild_name: out.guild_name,
+        //     guild_icon_url: out.guild_icon_url,
+        //     guild_size: out.guild_size
+        // }
+        return res.status(200).send(props)
+    } catch (err) {
+        return res.status(400).end()
+    }
+}
+
+export default Validate;
\ No newline at end of file
diff --git a/pages/api/nucleus/verify/verifyToken.js b/pages/api/nucleus/verify/verifyToken.js
new file mode 100644
index 0000000..b44624e
--- /dev/null
+++ b/pages/api/nucleus/verify/verifyToken.js
@@ -0,0 +1,15 @@
+import Axios from 'axios';
+import qs from 'querystring';
+
+const verifyToken = async (req, res) => {
+    const chk = await Axios.post('https://hcaptcha.com/siteverify', qs.stringify({
+        response: req.body.tkn,
+        secret: '0x19C699BFfce07b2a026121DE6702706BB2d51D6c',
+        sitekey: '85074411-fa13-4d9b-b901-53095c6d1fc6'
+    }))
+
+    // return res.send({ success: false });
+    return res.send({ success: chk.data.success });
+}
+
+export default verifyToken;
\ No newline at end of file
diff --git a/pages/api/rsmv/complete.js b/pages/api/rsmv/complete.js
index bc64d8a..002caee 100644
--- a/pages/api/rsmv/complete.js
+++ b/pages/api/rsmv/complete.js
@@ -1,7 +1,7 @@
 import Axios from 'axios';
 
 const Complete = async (req, res) => {
-    let code = await Axios.post('http://localhost:3000/api/rsmv/validate', {code:req.body.code});
+    let code = await Axios.post('http://127.0.0.1:3000/api/rsmv/validate', {code:req.body.code});
     if (code.status != 200) {
         return res.send(404);
     }
@@ -11,7 +11,7 @@
 
     let secret = "slwu0rZV5W6WdmGtgI16du8Ar2tQGMr3Q9dE6u3poKiVODNV9SweaA3buawgkTmTuITXDWOUpBcTFA0qWrUvoshi1JB180WOFwA7"
     let resp = await Axios.get(
-        `http://192.168.102.7:10000/role/gid/${req.body.gid}/rid/${req.body.rid}/user/${req.body.uid}/secret/${secret}/code/${req.body.code}`
+        `http://localhost:10000/verify/${req.body.gid}/${req.body.rid}/${req.body.uid}/${secret}/${req.body.code}`
     )
     return res.send(resp.status);
 }
diff --git a/pages/api/rsmv/validate.js b/pages/api/rsmv/validate.js
index d73c467..e0c4de1 100644
--- a/pages/api/rsmv/validate.js
+++ b/pages/api/rsmv/validate.js
@@ -2,7 +2,7 @@
 
 const Validate = async (req, res) => {
     try {
-        var out = await Axios.get(`http://192.168.102.7:10000/verify/${req.body.code}`)
+        var out = await Axios.get(`http://localhost:10000/verify/${req.body.code}`)
         out = out.data
         let props = {
             user: out.user,
diff --git a/pages/clicksforms.js b/pages/clicksforms.js
index e4d96dc..8da3441 100644
--- a/pages/clicksforms.js
+++ b/pages/clicksforms.js
@@ -2,7 +2,6 @@
 import Header from '../Components/Header'
 import { AutoLayout, Panel, Title, Subtitle, Text, Divider } from '../Components/Panels';
 import { List, ListItem, Code } from '../Components/Texttools';
-import Link from 'next/link';
 import React from 'react';
 
 export default class Home extends React.Component {
@@ -54,7 +53,7 @@
             <Title>Services</Title>
             <Divider toHighlight={this.state.toHighlight} highlightColour="6576CC" name="services"/>
             <Text>ClicksForms supports services such as <a href="https://docs.google.com/forms">Google Forms</a> through our Add-on.</Text>
-            <Text>Our API is public. You can view it <Link href="/clicksforms/docs">here</Link>.</Text>
+            <Text>Our API is public. You can view it <a href="/clicksforms/docs">here</a>.</Text>
           </Panel>
           <Panel halfSize={true} id="privacy">
             <Title>Privacy</Title>
diff --git a/pages/index.js b/pages/index.js
index f801b79..f84c7cd 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -7,7 +7,7 @@
     <>
       <Header
         name="Clicks"
-        subtext="// TODO: Fix this massive security issue"
+        subtext="Creating projects that click"
         customImage="https://assets.clicks.codes/web/logos/clicks.svg"
         embedImage="https://assets.clicks.codes/web/logos/clicks.png"
         gradient={["6576CC", "4B5899"]}
diff --git a/pages/nucleus.js b/pages/nucleus.js
new file mode 100644
index 0000000..5155597
--- /dev/null
+++ b/pages/nucleus.js
@@ -0,0 +1,116 @@
+import { Card, CardRow } from '../Components/Card';
+import Header from '../Components/Header'
+import { AutoLayout, Panel, Title, Subtitle, Text, Divider } from '../Components/Panels';
+import { List, ListItem, Code } from '../Components/Texttools';
+import { useColorMode } from 'theme-ui';
+
+export default function Home() {
+  const [theme, setTheme] = useColorMode()
+
+  return (
+    <>
+      <Header
+        name="Nucleus"
+        customImage="https://assets.clicks.codes/web/logos/nucleus.svg"
+        embedImage="https://assets.clicks.codes/bots/nucleus/normal.png"
+        subtext="The core of your server"
+        gradient={["F27878", "D96B6B"]}
+        wave="web/waves/header/nucleus"
+        buttons={[
+          // {color: "424242", buttonText: "FFFFFF", link: "#features", text: "Features"},
+          {color: "424242", buttonText: "FFFFFF", link: "#commands", text: "Commands"},
+          {color: "424242", buttonText: "FFFFFF", link: "#privacy", text: "Privacy"},
+          {color: "F27878", buttonText: "FFFFFF", link: "#invite", text: "Invite"}
+        ]}
+      />
+      <AutoLayout>
+        <Panel halfSize={true} id="commands">
+          <Title>General Commands</Title>
+          <Divider />
+          <Text>Standard commands to use Nucleus</Text>
+          <List colour="F27878">
+            <ListItem><Code colour="F27878">/help</Code> Shows all commands and info.</ListItem>
+            <ListItem><Code colour="F27878">/settings</Code> Shows all settings and info.</ListItem>
+            <ListItem>Theres a lot more settings commands but they&apos;re subject to change before release.</ListItem>
+            <ListItem>Expect this list to be longer</ListItem>
+          </List>
+        </Panel>
+        <Panel halfSize={true}>
+          <Title>Moderation Commands</Title>
+          <Divider />
+          <Text>Commands to manage your users and channels</Text>
+          <List colour="F27878">
+            <ListItem><Code colour="F27878">/mod warn</Code> Warns a member.</ListItem>
+            <ListItem><Code colour="F27878">/mod kick</Code> Kicks a member.</ListItem>
+            <ListItem><Code colour="F27878">/mod softban</Code> Soft bans a member.</ListItem>
+            <ListItem><Code colour="F27878">/mod ban</Code> Bans a member.</ListItem>
+            <ListItem><Code colour="F27878">/mod unban</Code> Unbans a member.</ListItem>
+            <ListItem><Code colour="F27878">/mod purge</Code> Deletes messages in the channel.</ListItem>
+            <ListItem><Code colour="F27878">/mod mute</Code> Mutes a member.</ListItem>
+            <ListItem><Code colour="F27878">/mod unmute</Code> Unmutes a member.</ListItem>
+            <ListItem><Code colour="F27878">/mod nick</Code> Changes the nickname of a member.</ListItem>
+            <ListItem><Code colour="F27878">/mod lock</Code> Stops people from sending messages in a channel.</ListItem>
+            <ListItem><Code colour="F27878">/mod slowmode</Code> Edits the slowmode in a channel.</ListItem>
+            <ListItem><Code colour="F27878">/mod viewas</Code> Allows you to view the server as a member or role.</ListItem>
+          </List>
+        </Panel>
+        <Panel halfSize={true}>
+          <Title>Internal Commands</Title>
+          <Divider />
+          <Text>Commands to check the status of and information about Nucleus</Text>
+          <List colour="F27878">
+            <ListItem><Code colour="F27878">/nucleus guide</Code> Shows the setup guide and tips for setup.</ListItem>
+            <ListItem><Code colour="F27878">/nucleus invite</Code> Shows the invite link for Nucleus.</ListItem>
+            <ListItem><Code colour="F27878">/nucleus ping</Code> Shows the latency of the bot.</ListItem>
+            <ListItem><Code colour="F27878">/nucleus stats</Code> Shows the stats of the bot.</ListItem>
+            <ListItem><Code colour="F27878">/nucleus suggest</Code> Sends a feature request to the developers.</ListItem>
+          </List>
+        </Panel>
+        <Panel halfSize={true} id="server">
+          <Title>Server Management</Title>
+          <Divider />
+          <Text>Commands to manage your server and members</Text>
+          <List colour="F27878">
+            <ListItem><Code colour="F27878">/server about</Code> Shows the server information.</ListItem>
+            <ListItem><Code colour="F27878">/server rules</Code> Shows the server rules.</ListItem>
+            <ListItem><Code colour="F27878">/ticket create</Code> Creates a ticket.</ListItem>
+            <ListItem><Code colour="F27878">/ticket close</Code> Closes a ticket.</ListItem>
+            <ListItem><Code colour="F27878">/user about</Code> Shows the user information.</ListItem>
+            <ListItem><Code colour="F27878">/user avatar</Code> Shows the user avatar.</ListItem>
+            <ListItem><Code colour="F27878">/user track</Code> Allows you to move a user up and down a role track.</ListItem>
+            <ListItem><Code colour="F27878">/verify</Code> Verifies a member to give them access to the server.</ListItem>
+          </List>
+        </Panel>
+        <Panel halfSize={false} id="verify">
+            <Title>Verification</Title>
+            <Divider />
+            <Text>Verification ensures all members in your server are human, and prevents automated accounts from joining.</Text>
+            <Text>For more information, see the <a href="/nucleus/verify/about">about</a> page.</Text>
+        </Panel>
+        <Panel halfSize={true} id="privacy">
+          <Title>Privacy</Title>
+          <Divider />
+          <Text>You can run <Code colour="F27878">/privacy</Code> to view and manage all data stored about your server</Text>
+          <Text>You should always know what we know and store about you, so <a href="https://clicksminuteper.github.io/policies/nucleus">here</a> is the complete list.</Text>
+        </Panel>
+        <Panel halfSize={true} id="invite">
+          <Title>Invite</Title>
+          <Divider />
+          <CardRow>
+            <Card
+              wave="nucleus"
+              icon="bots/nucleus/circle"
+              buttonText={"FFFFFF"} gradient={["F27878", "D96B6B"]}
+              title="Nucleus"
+              subtext="Invite Nucleus to your server"
+              buttons={[
+                  {color: "424242", link: "https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands", text: "Invite"}
+              ]}
+              url="https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands"
+            />
+          </CardRow>
+        </Panel>
+      </AutoLayout>
+    </>
+  )
+}
diff --git a/pages/nucleus/verify/about.js b/pages/nucleus/verify/about.js
new file mode 100644
index 0000000..08e7f00
--- /dev/null
+++ b/pages/nucleus/verify/about.js
@@ -0,0 +1,77 @@
+import React, { Component } from 'react'
+import Header from '../../../Components/Header'
+import { AutoLayout, Panel, Title, Subtitle, Text, Divider } from '../../../Components/Panels'
+import { Code } from '../../../Components/Texttools'
+import { Card, CardRow } from '../../../Components/Card'
+import HCaptcha from 'react-hcaptcha';
+import { useReward } from 'react-rewards';
+
+function About(props) {
+    const { reward, isAnimating } = useReward('confetti', 'confetti', {
+        elementSize: 12,
+        spread: 85,
+        position: "absolute",
+        colors: ["#F27878", "#E5AB71", "#E5DC71", "#A1CC65", "#68D49E", "#71AFE5", "#6576CC", "#8D58B2", "#BF5E9F"]
+    });
+
+    return (
+        <>
+            <Header
+                name="Nucleus Verification"
+                subtext="Remove automated accounts from your server"
+                customImage={"https://assets.clicks.codes/web/logos/nucleus.svg"}
+                embedImage={"https://assets.clicks.codes/bots/nucleus/normal.png"}
+                gradient={["F27878", "D96B6B"]}
+                wave="web/waves/header/nucleus"
+                buttons={[
+                    {color: "424242", buttonText: "FFFFFF", link: "#about", text: "About"},
+                    {color: "424242", buttonText: "FFFFFF", link: "#privacy", text: "Privacy"},
+                    {color: "F27878", buttonText: "FFFFFF", link: "#invite", text: "Invite"}
+                ]}
+            />
+            <AutoLayout>
+                <Panel halfSize={false} id="about">
+                    <Title>About Verification</Title>
+                    <Divider />
+                    <Text>Nucleus is designed to help keep your server safe. Verification is how we remove bots from your server.</Text>
+                    <Text>Many bot accounts are designed to join and spam in servers, and verification can prevent this easily:</Text>
+                    <HCaptcha
+                        id="Captchas mitigate problems"
+                        sitekey="85074411-fa13-4d9b-b901-53095c6d1fc6"
+                        onVerify={reward}
+                        theme="dark"
+                    />
+                    <Text>Users will need to run <Code colour="F27878">/verify</Code> when they join, and will be given a link to complete this check online.</Text>
+                    <Text>It is completely free to use verification, and for users to verify.</Text>
+                    <div id="confetti" />
+                </Panel>
+                <Panel halfSize={true} id="privacy">
+                    <Title>Privacy</Title>
+                    <Divider />
+                    <Text>Verification stores the smallest amount of data required to function, and is deleted automatically.</Text>
+                    <Text>This includes the user&apos;s ID, the server ID, role name and server icon.</Text>
+                    <Text>The full list of data stored by Nucleus can be found <a href="https://clicksminuteper.github.io/policies/nucleus">here</a>.</Text>
+                </Panel>
+                <Panel halfSize={true} id="invite">
+                    <Title>Invite</Title>
+                    <Divider />
+                    <CardRow>
+                        <Card
+                            wave="nucleus"
+                            icon="bots/nucleus/circle"
+                            buttonText={"FFFFFF"} gradient={["F27878", "D96B6B"]}
+                            title="Nucleus"
+                            subtext="Invite Nucleus to your server"
+                            buttons={[
+                                {color: "424242", link: "https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands", text: "Invite"}
+                            ]}
+                            url="https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands"
+                        />
+                    </CardRow>
+                </Panel>
+            </AutoLayout>
+        </>
+    )
+}
+
+export default About;
\ No newline at end of file
diff --git a/pages/nucleus/verify/alreadyVerified.js b/pages/nucleus/verify/alreadyVerified.js
new file mode 100644
index 0000000..c31290a
--- /dev/null
+++ b/pages/nucleus/verify/alreadyVerified.js
@@ -0,0 +1,24 @@
+import { Component } from 'react'
+import Header from '../../../Components/Header'
+
+class Failed extends Component {
+    constructor(props) {
+        super(props)
+    }
+
+    render() {
+        return (
+            <Header
+                name="Already verified"
+                subtext="You are already verified, and cannot verify again"
+                gradient={["65CC76", "60B258"]}
+                wave="web/waves/header/nucleus"
+                buttons={[]}
+                fullscreen={true}
+            />
+        )
+    }
+
+}
+
+export default Failed;
\ No newline at end of file
diff --git a/pages/nucleus/verify/failure.js b/pages/nucleus/verify/failure.js
new file mode 100644
index 0000000..61b58d0
--- /dev/null
+++ b/pages/nucleus/verify/failure.js
@@ -0,0 +1,24 @@
+import { Component } from 'react'
+import Header from '../../../Components/Header'
+
+class Failed extends Component {
+    constructor(props) {
+        super(props)
+    }
+
+    render() {
+        return (
+            <Header
+                name="Verification failed"
+                subtext={<p>Please try again, and if the error persists please contact us at <a href="mailto:verification@clicks.codes" target="_blank" rel="noopener noreferrer">verification@clicks.codes</a></p>}
+                gradient={["F27878", "D96B6B"]}
+                wave="web/waves/header/nucleus"
+                buttons={[]}
+                fullscreen={true}
+            />
+        )
+    }
+
+}
+
+export default Failed;
\ No newline at end of file
diff --git a/pages/nucleus/verify/index.js b/pages/nucleus/verify/index.js
new file mode 100644
index 0000000..796298a
--- /dev/null
+++ b/pages/nucleus/verify/index.js
@@ -0,0 +1,134 @@
+import HCaptcha from 'react-hcaptcha';
+import Axios from 'axios';
+import Router from 'next/router';
+import React from 'react';
+import Header from '../../../Components/Header'
+import { useReward } from 'react-rewards';
+import { Card, CardRow } from '../../../Components/Card';
+
+import { AutoLayout, Panel, Title, Text, Divider } from '../../../Components/Panels';
+import { List, ListItem } from '../../../Components/Texttools';
+import { useColorMode } from 'theme-ui';
+
+function Verify(props) {
+    const [clicked, setClicked] = React.useState(false);
+    const [theme, setTheme] = useColorMode()
+
+    if (clicked) {
+        Router.push('/nucleus/verify/alreadyVerified', '/nucleus/verify/success');
+    }
+
+    const { reward: reward, isAnimating: isAnimating } = useReward('confetti', 'confetti', {
+        elementSize: 10,
+        elementCount: 150,
+        startVelocity: 35,
+        lifetime: 300,
+        decay: 0.94,
+        spread: 170,
+        position: "absolute",
+        colors: ["#68D49E"]
+    });
+
+    async function submitForm(tkn) {
+        if ( clicked ) {
+            return
+        }
+        setClicked(true);
+        reward();
+        let code = await Axios.post('/api/nucleus/verify/complete', {
+            code: props.code,
+            tkn: tkn
+        });
+        setTimeout(() => {
+            if (code.data.success === true ) return Router.push('/nucleus/verify/success','/nucleus/verify')
+            else return Router.push('/nucleus/verify/failure','/nucleus/verify')
+        }, 2500);
+    }
+
+    return <>
+        <Header
+            name={props.guild_name}
+            customImage={props.guild_icon_url}
+            roundImage={true}
+            subtext={`${props.memberCount} members`}
+            gradient={["F27878", "D96B6B"]}
+            wave="web/waves/header/nucleus"
+            buttons={[]}
+        />
+        <AutoLayout>
+            <Panel>
+                <Title>Verify</Title>
+                <Divider name="commands"/>
+                <Text>Complete the check below to join {props.guild_name}</Text>
+                <div style={{height: "125px"}}>
+                    <HCaptcha
+                        id="Captchas mitigate problems"
+                        sitekey="85074411-fa13-4d9b-b901-53095c6d1fc6"
+                        onVerify={tkn => submitForm(tkn)}
+                        theme="dark"
+                    />
+                </div>
+                <List colour="F27878">
+                    <ListItem>This is an automatic check performed by Nucleus.</ListItem>
+                    <ListItem>By clicking Proceed, you will be given the <code>{props.role_name}</code> role in <code>{props.guild_name}</code>.</ListItem>
+                    <ListItem>For the full list of data stored by Nucleus, please check <a href="https://clicksminuteper.github.io/policies/nucleus#verification">here</a></ListItem>
+                </List>
+                <div id="confetti" />
+            </Panel>
+            <Panel halfSize={false} id="invite">
+            <Title>Invite</Title>
+            <Divider />
+            <CardRow>
+                <Card
+                    wave="nucleus"
+                    icon="bots/nucleus/circle"
+                    buttonText={"FFFFFF"} gradient={["F27878", "D96B6B"]}
+                    title="Nucleus"
+                    subtext="Invite Nucleus to your server"
+                    buttons={[
+                        {color: "424242", link: "https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands", text: "Invite"}
+                    ]}
+                    url="https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands"
+                />
+            </CardRow>
+        </Panel>
+        </AutoLayout>
+    </>
+}
+
+export default Verify;
+export async function getServerSideProps(ctx) {
+    if(!ctx.query.code) {
+        return {
+            redirect: {
+                destination: '/nucleus/verify/about',
+                permanent: true
+            }
+        }
+    }
+    let code;
+    try {
+        await Axios.patch(`http://localhost:10000/verify/${ctx.query.code}`);
+        code = await Axios.get(`http://localhost:10000/verify/${ctx.query.code}`, {code:ctx.query.code});
+    } catch (e) {
+        return {
+            redirect: {
+                destination: '/nucleus/verify/failure',
+                permanent: true
+            }
+        }
+    }
+    let headers = ctx.req.headers;
+    return {
+        props: {
+            uID: code.data.uID,
+            role_name: code.data.rName,
+            gID: code.data.gID,
+            guild_name: code.data.gName,
+            guild_icon_url: code.data.gIcon,
+            memberCount: code.data.mCount,
+            headers: headers,
+            code: ctx.query.code
+        }
+    }
+}
\ No newline at end of file
diff --git a/pages/nucleus/verify/success.js b/pages/nucleus/verify/success.js
new file mode 100644
index 0000000..de5b4d8
--- /dev/null
+++ b/pages/nucleus/verify/success.js
@@ -0,0 +1,24 @@
+import { Component } from 'react'
+import Header from '../../../Components/Header'
+
+class Success extends Component {
+    constructor(props) {
+        super(props)
+    }
+
+    render() {
+        return (
+            <Header
+                name="Verified"
+                subtext="You can now close this tab or window."
+                gradient={["65CC76", "60B258"]}
+                wave="web/waves/header/rsm"
+                buttons={[]}
+                fullscreen={true}
+            />
+        )
+    }
+
+}
+
+export default Success;
\ No newline at end of file
diff --git a/pages/nucleus/verify/testing.js b/pages/nucleus/verify/testing.js
new file mode 100644
index 0000000..42ac53d
--- /dev/null
+++ b/pages/nucleus/verify/testing.js
@@ -0,0 +1,95 @@
+import HCaptcha from 'react-hcaptcha';
+import Axios from 'axios';
+import Router from 'next/router';
+import React from 'react';
+import Header from '../../../Components/Header'
+import { useReward } from 'react-rewards';
+import { Card, CardRow } from '../../../Components/Card'
+
+import { AutoLayout, Panel, Title, Text, Divider } from '../../../Components/Panels';
+import { List, ListItem } from '../../../Components/Texttools';
+import { useColorMode } from 'theme-ui';
+
+function Verify(props) {
+    const [clicked, setClicked] = React.useState(false);
+    const [theme, setTheme] = useColorMode()
+
+    const { reward: reward, isAnimating: isAnimating } = useReward('confetti', 'confetti', {
+        elementSize: 10,
+        elementCount: 150,
+        startVelocity: 35,
+        lifetime: 300,
+        decay: 0.94,
+        spread: 170,
+        position: "absolute",
+        colors: ["#68D49E"]
+    });
+
+    async function submitForm(tkn) {
+        if ( clicked ) {
+            return
+        }
+        setClicked(true);
+        reward();
+        let code = await Axios.post('/api/nucleus/verify/complete', {
+            code:"TEST",
+            tkn: tkn
+        });
+        setTimeout(() => {
+            if (code.data.success === true ) return Router.push('/nucleus/verify/success','/nucleus/verify')
+            else return Router.push('/nucleus/verify/failure','/nucleus/verify')
+        }, 2500);
+    }
+
+    return <>
+        <Header
+            name="Clocks finite state machine"
+            customImage={"https://i1.sndcdn.com/artworks-000045941811-q634od-t500x500.jpg"}
+            roundImage={true}
+            subtext={`-5 members`}
+            gradient={["F27878", "D96B6B"]}
+            wave="web/waves/header/nucleus"
+            buttons={[]}
+        />
+        <AutoLayout>
+            <Panel>
+                <Title>Verify</Title>
+                <Divider name="commands"/>
+                <Text>Complete the check below to join ERROR</Text>
+                <div style={{height: "125px"}}>
+                    <HCaptcha
+                        id="Captchas mitigate problems"
+                        sitekey="85074411-fa13-4d9b-b901-53095c6d1fc6"
+                        onVerify={tkn => submitForm(tkn)}
+                        theme="dark"
+                    />
+                </div>
+                <List colour="F27878">
+                    <ListItem>This is an automatic check performed by Nucleus.</ListItem>
+                    <ListItem>By completing the CAPTCHA, you will be given the <code>MISSING</code> role in <code>ERROR</code>.</ListItem>
+                    <ListItem>For the full list of data stored by Nucleus, please check <a href="https://clicksminuteper.github.io/policies/nucleus#verification">here</a></ListItem>
+                </List>
+                <div id="confetti" />
+            </Panel>
+            <Panel halfSize={false} id="invite">
+                <Title>Invite</Title>
+                <Divider />
+                <CardRow>
+                    <Card
+                        wave="nucleus"
+                        icon="bots/nucleus/circle"
+                        buttonText={"FFFFFF"} gradient={["F27878", "D96B6B"]}
+                        title="Nucleus"
+                        subtext="Invite Nucleus to your server"
+                        buttons={[
+                            {color: "424242", link: "https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands", text: "Invite"}
+                        ]}
+                        url="https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands"
+                    />
+                </CardRow>
+            </Panel>
+        </AutoLayout>
+    </>
+}
+
+export default Verify;
diff --git a/pages/privacy.js b/pages/privacy.js
new file mode 100644
index 0000000..db621c5
--- /dev/null
+++ b/pages/privacy.js
@@ -0,0 +1,34 @@
+import Header from '../Components/Header'
+import { AutoLayout, Panel, Title, Subtitle, Text, Divider } from '../Components/Panels';
+import { List, ListItem, Code } from '../Components/Texttools';
+
+
+export default function Home() {
+    return (
+        <>
+            <Header
+                name="Privacy"
+                subtext="Privacy is a right - Here's how we handle it"
+                gradient={["71AFE5", "6576CC"]}
+                wave="web/waves/header/clicksforms"
+                buttons={[]}
+            />
+            <AutoLayout>
+                <Panel halfSize={true}>
+                    <Title>Transparency</Title>
+                    <Text>Everything we store about you and your Discord servers will be listed.</Text>
+                    <List colour={"6576CC"}>
+                        <ListItem><a href="https://clicksminuteper.github.io/policies/rsm">RSM</a></ListItem>
+                        <ListItem><a href="https://clicksminuteper.github.io/policies/clicksforms">ClicksForms</a></ListItem>
+                        <ListItem>GPS does not store any information</ListItem>
+                    </List>
+                    <Text>Have any questions or concerns? <a href="/support">Let us know</a> and we can investigate if you believe there are any mistakes</Text>
+                </Panel>
+                <Panel halfSize={true}>
+                    <Title>Security</Title>
+                    <Text>We will do everything we can to protect user data, including high security. You can <a href="/support">message us</a> if you would like to learn more about how we do this</Text>
+                </Panel>
+            </AutoLayout>
+        </>
+    )
+}
diff --git a/pages/rsmv/index.js b/pages/rsmv/index.js
index 175a271..f46c46e 100644
--- a/pages/rsmv/index.js
+++ b/pages/rsmv/index.js
@@ -4,7 +4,7 @@
 import Axios from 'axios';
 import Router from 'next/router';
 import React from 'react';
-import Header from '../../Components/Header'
+import Header from '../../Components/Header';
 
 import { AutoLayout, Panel, Title, Subtitle, Text, Divider } from '../../Components/Panels';
 import { List, ListItem, Code } from '../../Components/Texttools';
diff --git a/styles/globals.module.css b/styles/globals.module.css
new file mode 100644
index 0000000..bed3151
--- /dev/null
+++ b/styles/globals.module.css
@@ -0,0 +1,19 @@
+.container {
+    position: fixed;
+    top: 42px;
+    height: calc(100vh - 42px);
+    width: 100%;
+    border-radius: 25px;
+    box-shadow: 0 0 0 100px black;
+    pointer-events: none;
+    background: transparent;
+}
+
+.container::-webkit-scrollbar {
+    display: none;
+}
+
+.container, .container * {
+    transform: rotateY(0);
+    -webkit-transform: rotateY(0);
+}
\ No newline at end of file
diff --git a/styles/nucleus/nucleus.module.css b/styles/nucleus/nucleus.module.css
new file mode 100644
index 0000000..391ddc0
--- /dev/null
+++ b/styles/nucleus/nucleus.module.css
@@ -0,0 +1,43 @@
+.center {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    flex-direction: column;
+    padding: 10px;
+}
+
+.center * {
+    margin-bottom: 20px;
+}
+
+.text {
+	color: var(--card-text-color);
+	font-size: 18px;
+    text-align: center;
+    padding-left: 10px;
+    padding-right: 10px;
+}
+
+.button {
+    border-radius: 5px;
+    background-color: var(--card-background-color);
+    color: var(--card-text-color);
+    border: 3px solid #F27878;
+    font-size: 20px;
+    padding-left: 10px;
+    padding-right: 10px;
+    margin-top: -40px;
+    transition: 0.3s;
+}
+
+.buttonComplete {
+    border: 3px solid #65CC76;
+}
+
+.button.clicked {
+    color: #F27878;
+}
+
+.buttonComplete.clicked {
+    color: #65CC76;
+}
diff --git a/todo/roles/about.js b/todo/roles/about.js
new file mode 100644
index 0000000..3c86b9a
--- /dev/null
+++ b/todo/roles/about.js
@@ -0,0 +1 @@
+export default function About(props) {}
\ No newline at end of file
diff --git a/todo/roles/failure.js b/todo/roles/failure.js
new file mode 100644
index 0000000..e188b06
--- /dev/null
+++ b/todo/roles/failure.js
@@ -0,0 +1 @@
+export default function Failure(props) {}
\ No newline at end of file
diff --git a/todo/roles/index.js b/todo/roles/index.js
new file mode 100644
index 0000000..8ddc9b8
--- /dev/null
+++ b/todo/roles/index.js
@@ -0,0 +1,92 @@
+import { Component } from 'react';
+import Styles from '../../../styles/nucleus/nucleus.module.css'
+import HCaptcha from 'react-hcaptcha';
+import Axios from 'axios';
+import Router from 'next/router';
+import React from 'react';
+import Header from '../../../Components/Header';
+
+import { AutoLayout, Panel, Title, Subtitle, Text, Divider } from '../../../Components/Panels';
+import { List, ListItem, Code } from '../../../Components/Texttools';
+
+class Verify extends Component {
+    constructor(props) {
+        super(props);
+        this.v = false;
+        this.state = {
+            captchaComplete: false,
+            clicked: false
+        }
+    }
+
+    async handleVerificationSuccess(cls, token) {
+        const chk = await Axios.put('/api/nucleus/verifyTkn', { tkn: token.toString() })
+        if(chk.data.success == true) {
+            this.setState({
+                captchaComplete: true
+            })
+            return cls.v = true;
+        } else {
+            return;
+        }
+    }
+
+    async submitForm(cls) {
+        if ( cls.state.clicked ) {
+            return
+        }
+        cls.setState({
+            clicked: true
+        })
+        if (!cls.v) {
+            return Router.push('/nucleus/verify/failure','/nucleus/verify/failure')
+        }
+        let code = await Axios.post('/api/nucleus/complete', {
+            uid:cls.props.uID,
+            rid:cls.props.rID,
+            gid:cls.props.gID,
+            code:cls.props.code
+        });
+        if (code.status === 200 ) return Router.push('/nucleus/verify/success','/nucleus/verify/success')
+        else return Router.push('/nucleus/verify/failure','/nucleus/verify/failure')
+    }
+
+    render() {
+        return <>
+            <Header
+                name={this.props.guild_name}
+                customImage={this.props.guild_icon_url}
+                roundImage={true}
+                subtext={`${this.props.memberCount} members`}
+                gradient={["F27878", "D96B6B"]}
+                wave="web/waves/header/nucleus"
+                buttons={[]}
+            />
+            <AutoLayout>
+                <Panel>
+                    <Text>Complete the check below to join {this.props.guild_name}</Text>
+                    <div style={{height: "125px"}}>
+                        <HCaptcha
+                            id="Captchas mitigate problems"
+                            sitekey="85074411-fa13-4d9b-b901-53095c6d1fc6"
+                            onVerify={token => this.handleVerificationSuccess(this, token)}
+                            theme={this.theme ? "light" : "dark"}
+                        />
+                    </div>
+                    <button type="button" className={Styles.button + " " + (this.state.captchaComplete ? Styles.buttonComplete : null)} onClick={(success) => this.submitForm(this)}>Proceed</button>
+                    <List colour="F27878">
+                        <ListItem>This is an automatic check performed by Nucleus.</ListItem>
+                        <ListItem>By clicking Proceed, you will be given the <code>{this.props.role_name}</code> role in <code>{this.props.guild_name}</code>.</ListItem>
+                        <ListItem>For the full list of data stored by Nucleus, please check <a href="https://clicksminuteper.github.io/policies/nucleus#verification">here</a></ListItem>
+                    </List>
+                    <Text>You can add Nucleus to your server by inviting it <a href="https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands">here</a>.</Text>
+                    <div id="confetti" />
+                </Panel>
+            </AutoLayout>
+        </>
+    }
+}
+
+export default Verify;
+export async function getServerSideProps(ctx) {
+}
\ No newline at end of file
diff --git a/todo/roles/success.js b/todo/roles/success.js
new file mode 100644
index 0000000..f7155ed
--- /dev/null
+++ b/todo/roles/success.js
@@ -0,0 +1 @@
+export default function Success(props) {}
\ No newline at end of file