diff --git a/.gitignore b/.gitignore
index f70c4d540..3c497fef9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,3 +50,5 @@ generated
# DecapCMS
out/
+
+certificates
\ No newline at end of file
diff --git a/public/admin/config.yml b/public/admin/config.yml
index 6936b1ce7..45a4cc645 100644
--- a/public/admin/config.yml
+++ b/public/admin/config.yml
@@ -1,6 +1,9 @@
backend:
name: github
repo: public-convenience-ltd/toiletmap
+ site_domain: toiletmap.org.uk
+ base_url: https://toiletmap.org.uk
+ auth_endpoint: api/decap-oauth
site_url: https://toiletmap.org.uk/
display_url: https://toiletmap.org.uk/
publish_mode: editorial_workflow
diff --git a/public/admin/index.html b/public/admin/index.html
deleted file mode 100644
index 2bf7314aa..000000000
--- a/public/admin/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
- Content Manager
-
-
-
-
-
-
-
diff --git a/src/pages/api/admin.page.tsx b/src/pages/api/admin.page.tsx
new file mode 100644
index 000000000..97232ba49
--- /dev/null
+++ b/src/pages/api/admin.page.tsx
@@ -0,0 +1,23 @@
+import { NextApiRequest, NextApiResponse } from 'next';
+
+async function handler(req: NextApiRequest, res: NextApiResponse) {
+ res.setHeader('Content-Type', 'text/html');
+ return res.send(`
+
+
+
+
+
+
+
+ Content Manager
+
+
+
+
+
+
+ `);
+}
+
+export default handler;
diff --git a/src/pages/api/decap-oauth/callback.page.ts b/src/pages/api/decap-oauth/callback.page.ts
new file mode 100644
index 000000000..db7370707
--- /dev/null
+++ b/src/pages/api/decap-oauth/callback.page.ts
@@ -0,0 +1,59 @@
+import { NextApiRequest, NextApiResponse } from 'next';
+import { clientId, clientSecret, tokenUrl } from './config';
+
+export default async function handler(
+ req: NextApiRequest,
+ res: NextApiResponse,
+) {
+ const data = {
+ code: req.query?.code as string,
+ client_id: clientId,
+ client_secret: clientSecret,
+ };
+
+ try {
+ const accessTokenResponse = await fetch(tokenUrl, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(data),
+ });
+
+ if (!accessTokenResponse.ok) {
+ throw new Error(
+ `Failed to fetch access token: ${accessTokenResponse.statusText}`,
+ );
+ }
+
+ const body = await accessTokenResponse.json();
+
+ const authContent = {
+ token: body.access_token,
+ provider: 'github',
+ };
+
+ const script = `
+
+ `;
+
+ res.setHeader('Content-Type', 'text/html');
+ return res.send(script);
+ } catch (err) {
+ console.log(err);
+ return res.redirect('/?error=decap_oauth_error');
+ }
+}
diff --git a/src/pages/api/decap-oauth/config.ts b/src/pages/api/decap-oauth/config.ts
new file mode 100644
index 000000000..3739587b7
--- /dev/null
+++ b/src/pages/api/decap-oauth/config.ts
@@ -0,0 +1,5 @@
+export const clientId = process.env.DECAP_OAUTH_GITHUB_CLIENT_ID;
+export const clientSecret = process.env.DECAP_OAUTH_GITHUB_CLIENT_SECRET;
+
+export const authUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}&scope=repo,user`;
+export const tokenUrl = 'https://github.com/login/oauth/access_token';
diff --git a/src/pages/api/decap-oauth/index.page.ts b/src/pages/api/decap-oauth/index.page.ts
new file mode 100644
index 000000000..582b73a56
--- /dev/null
+++ b/src/pages/api/decap-oauth/index.page.ts
@@ -0,0 +1,6 @@
+import { authUrl } from './config';
+import type { NextApiRequest, NextApiResponse } from 'next';
+
+export default function handler(_: NextApiRequest, res: NextApiResponse) {
+ res.redirect(authUrl);
+}