At the moment Imput only supports Github as a backend, but other Git providers are planned for the future. Sorry! 😺
Choosing your backend
In Imput terms a backend is the git provider you'll save your content to. Github, Gitlab, Bitbucket, etc. all have public APIs that all work slightly differently which requires completely new implementations on our side.
Each time you save a piece of content or upload media, Imput will use your provider's API to sync the changes to your git provider. Think of it as setting up a database and an API, but without the hassle.
Setting up Github as your backend
If you've been following along with the documentation, your Imput config should look something like this right now:
const CMS = () => (
<ImputCMS
{
...{
// your settings will go here!
}
}
/>
)
Your configuration should follow this shape:
const CMS = () => (
<ImputCMS
{...{
settings: {
backend: {
name: 'github',
repo: '{your github username}/{your repo name}',
branch: 'main', // the branch you want to edit, usually main or master
base_url: 'https://mysite.com/', // the root address of your site
auth_endpoint: 'api/authorize', // where your auth endpoint is located
},
},
}}
/>
)
Getting your oAuth secrets
Imput leaves the authentication up to you, which means you need to set up an oAuth endpoint that will set a cookie to allow you to access your repo. First of all you'll need to create a new oAuth application and get your secret tokens. Go to your Github settings and follow along with the video.
Then you'll want to add both of these secrets to your .env
file:
OAUTH_GITHUB_CLIENT_ID={your github client id}
OAUTH_GITHUB_CLIENT_SECRET={your github client secret}
Create your endpoints
The endpoints here are specific to Next.js, but the logic should be exactly the same for any other API framework. The only difference will be how you get certain headers.
If you're having trouble open an issue on Github and we'll add it to the docs.
First create a config file for your oAuth, this file will tell our endpoints where to login on Github's side.:
// lib/config.ts
export const config = (provider: "github") => ({
client: {
id: client[provider].id as string,
secret: client[provider].secret as string,
},
auth: {
tokenHost: auth[provider].tokenHost,
tokenPath: auth[provider].tokenPath,
authorizePath: auth[provider].authorizePath,
},
});
const auth = {
github: {
tokenHost: "https://github.com",
tokenPath: "/login/oauth/access_token",
authorizePath: "/login/oauth/authorize",
},
};
const client = {
github: {
id: process.env.OAUTH_GITHUB_CLIENT_ID,
secret: process.env.OAUTH_GITHUB_CLIENT_SECRET,
},
};
Then we'll create our endpoints. For this we'll use an external dependency:
npm install simple-oauth2
Then create the auth endpoint, this will generate your Github login link and send you to it:
// app/api/authorize/route.ts
import { AuthorizationCode } from 'simple-oauth2'
import { randomBytes } from 'crypto'
import { config } from '../../../lib/config'
import { scopes } from '../../../lib/scopes'
const randomString = () => randomBytes(4).toString('hex')
export async function GET(request: Request) {
const host = request.headers.get('host')
// this switches protocol depending on env
const protocol =
process.env.NODE_ENV === 'production' ? 'https://' : 'http://'
const url = new URL(`https://${host}/${request.url}`)
const urlParams = url.searchParams
const provider = urlParams.get('provider') as 'github' | 'gitlab'
const client = new AuthorizationCode(config(provider))
console.log('host', host)
console.log('provider', provider)
console.log(`${protocol}${host}/api/callback?provider=${provider}`)
const authorizationUri = client.authorizeURL({
redirect_uri: `${protocol}${host}/api/callback?provider=${provider}`,
scope: scopes[provider],
state: randomString(),
})
return Response.redirect(authorizationUri)
}
Then you'll need to set up your callback endpoint, this one will receive the token from Github and send it back to Imput:
// pages/api/callback/route.ts
import { AuthorizationCode } from 'simple-oauth2'
import { randomBytes } from 'crypto'
import { config } from '../../../lib/config'
export async function GET(request: Request) {
const host = request.headers.get('host')
const protocol =
process.env.NODE_ENV === 'production' ? 'https://' : 'http://'
const url = new URL(`https://${host}/${request.url}`)
const urlParams = url.searchParams
const code = urlParams.get('code') as string
const provider = urlParams.get('provider') as 'github' | 'gitlab'
const client = new AuthorizationCode(config(provider))
const tokenParams = {
code,
redirect_uri: `${protocol}${host}/api/callback?provider=${provider}`,
}
try {
const accessToken = await client.getToken(tokenParams)
const token = accessToken.token['access_token']
console.log({
url: request.url,
code,
token,
provider,
})
return new Response(
`
<script type="text/javascript">
if (window.opener) {
window.opener.postMessage('${JSON.stringify({
token,
provider,
})}', "*");
}
window.close();
</script>
`,
{
headers: {
'Content-Type': 'text/html',
},
}
)
} catch (e) {
const error = e as any
return new Response(
`
<script>
event.source.postMessage(
'authorization:${error.provider}:error:${JSON.stringify(
error
)}',
message.origin
);
</script>
`,
{
headers: {
'Content-Type': 'text/html',
},
}
)
}
}
Once these two endpoints are in place you should be able to visit your CMS page (the one you created in "Getting Started" and use the Login button to login.
If you want to login on localhost you're going to have to make sure you swap https://
for http://
where appropriate.
The examples above handle it for you!
Next, we'll set up your content categories 👉