Hosting an Alinea backend requires several services such as storing and retrieving drafts, publishing changes and authenticating users. We go through each of these and combine them into a handler which can be hosted on Node.js or serverless/edge Javascript runtimes. Let's start by adjusting the alinea.config.tsx file to include the backend setup.
Make sure you've exported the dashboard first
import {alinea} from 'alinea'
import {backend} from 'alinea/core'
import {passwordLess} from 'alinea/auth.passwordless'
import {configureBackend} from './alinea.server'
export const config = alinea.createConfig({
backend: backend({
auth: passwordLess
}).configure(configureBackend),
...config
})
We set up the backend in a separate alinea.server.ts file that can be imported from the main alinea config. This file will hold all the configuration for the server side of the custom backend. When importing files that end with .server alinea makes sure they're not included in the client bundle, so your secrets are safe.
import {PasswordLess} from 'alinea/auth.passwordless'
import {Backend, JsonLoader} from 'alinea/backend'
import {GithubData} from 'alinea/backend.github'
import {RedisDrafts} from 'alinea/backend.redis/RedisDrafts'
import {JWTPreviews} from 'alinea/backend/util/JWTPreviews'
import {backend} from 'alinea/core'
import Redis from 'ioredis'
import {createTransport} from 'nodemailer'
export const configureBackend = backend.configure<PasswordLess>(
({auth, config, createStore}) => {
// The authentication service needs to link to your admin panel
// to create magic links and email them
const dashboardUrl = 'https://alinea.sh/admin.html'
// Configure the server side of the passwordless service
const passwordless = auth.configure({
dashboardUrl,
// This is the subject of the magic link mails
subject: 'Login',
// Send the mails from this address
from: `"Alinea" <no-reply@alinea.sh>`,
// We pass a nodemailer transporter so the service can send mails
transporter: createTransport(
// Pass all the required transport configuration options
// See: http://nodemailer.com/smtp/
{...smtpConfig}
),
// A secret is needed to sign the magic link tokens
jwtSecret: process.env.JWT_SECRET!,
// Email adresses pass through here while logging in,
// return true when a user is valid and is allowed to log in
async isUser(email: string) {
return email.endsWith('@alinea.sh')
}
})
// Create a drafts instance that will save and retrieve drafts from Redis
const drafts = new RedisDrafts({
client: new Redis(process.env.REDIS_DSN)
})
// Publish content changes to Github
const data = new GithubData({
config,
loader: JsonLoader,
// Pass a token which is authorized to read and write to the repository
githubAuthToken: process.env.GITHUB_TOKEN!,
owner: 'alineacms',
repo: 'alinea',
branch: 'main',
author: {
name: 'My Name',
email: 'me@example.com'
}
})
return new Backend({
dashboardUrl,
auth: passwordless,
config,
createStore,
drafts,
target: data,
media: data,
previews: new JWTPreviews(process.env.JWT_SECRET!)
})
}
)
The authentication service is the only one that provides not only a server implementation, but also a client part (the login screen). This is why the setup is included in the config file itself which is read by the client as well. We use the @alinea/auth.passwordless package. It can authenticate users with a magic link. It's ideal for serverless environments as it does not require a persistence layer. Install the backend and the nodemailer library which will handle sending emails.
npm install @alinea/auth.passwordless nodemailer
In the example we sync drafts to and from a Redis store. You can create a free persistent Redis store at upstash.io to get started. Install the backend and the ioredis library which will handle the connection.
npm install @alinea/backend.redis ioredis
Another package is available to sync to Firebase.
If you're setting up Alinea to run fully inside the browser (like we did with our demo) drafts can be synced to IndexedDB.
To publish content back to the git repository and store uploaded files we need a service that can handle that. Currently there is one package available to publish to Github hosted repositories. You'll have to create a token with read and write access to your repository.
npm install @alinea/backend.github