Azure has ready-made adapters, so you implement no storage yourself.
1. Install
npm install @xtrable-ltd/nanoesis @azure/storage-blob
2. Create two containers
In your storage account, add a private working container for editable files, and turn on Static website (which creates the $web container) for the published site.
3. Wire the editor
// editor.js
import { createEditor, devNoAuth } from '@xtrable-ltd/nanoesis/editor-api';
import { AzureBlobContainer, azureStorage } from '@xtrable-ltd/nanoesis/adapter-azure-blob';
import { createSharpEncoder } from '@xtrable-ltd/nanoesis/adapter-sharp';
const working = AzureBlobContainer.fromConnectionString(process.env.DATA_CONN, 'working');
const web = AzureBlobContainer.fromConnectionString(process.env.SITE_CONN, '$web');
export const editor = createEditor({
editorFiles: azureStorage(working),
website: azureStorage(web),
login: devNoAuth(), // swap for real login, see step 6
images: createSharpEncoder(), // responsive images
enumerate: () => working.list(''), // lets the editor self-heal its index
});
4. Serve it from a Function
One function for the API, one for the editor UI.
// functions.js
import { app } from '@azure/functions';
import { serveEditorAsset } from '@xtrable-ltd/nanoesis/editor-api';
import { editorDist } from '@xtrable-ltd/nanoesis/editor';
import { editor } from './editor.js';
app.http('api', {
route: 'api/{*rest}',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
authLevel: 'anonymous',
handler: async (req) => {
const url = new url(req.url);
const r = await editor.handleApi({
method: req.method,
path: url.pathname,
query: url.searchParams,
getHeader: (n) => req.headers.get(n) ?? undefined,
body: async () => new Uint8Array(await req.arrayBuffer()),
});
return { status: r.status, headers: r.headers, body: r.body };
},
});
app.http('spa', {
route: '{*path}',
methods: ['GET'],
authLevel: 'anonymous',
handler: async (req) => {
const a = await serveEditorAsset(editorDist, new url(req.url).pathname);
return { status: a.status, headers: a.headers, body: a.body };
},
});
5. Publish
Deploy the Function, open it, and press Publish. The built site is written to $web and served at your account's static-website endpoint. Put a CDN in front for a custom domain.
6. Add real login
Replace devNoAuth() with the local-jwt provider, passing your user store and a secret:
import { createLocalJwtAuth } from '@xtrable-ltd/nanoesis/adapter-local-jwt';
const { identity, endpoints, userAdmin } = createLocalJwtAuth({
users, // your user store
signingSecret: process.env.JWT_SECRET,
});
// in createEditor: login: identity, authEndpoints: endpoints, userAdmin
That is the exact setup this site runs on.