Skip to content

Deployment

TIP

Run API and frontend in separate runtimes for security.

Cloudflare Workers

typescript
// src/index.ts
import { buildJsonApi } from 'laikacms/storage-api';
import { R2StorageRepository } from 'laikacms/storage-r2';
import { markdownSerializer } from 'laikacms/storage-serializers-markdown';

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const repo = new R2StorageRepository(env.CONTENT_BUCKET, { md: markdownSerializer }, 'md');
    const api = buildJsonApi({ repo });
    return api.fetch(request);
  },
};
toml
# wrangler.toml
name = "laika-api"
main = "src/index.ts"
compatibility_date = "2024-01-01"

[[r2_buckets]]
binding = "CONTENT_BUCKET"
bucket_name = "content"

Deploy: wrangler deploy

Node.js

typescript
import { serve } from '@hono/node-server';
import { buildJsonApi } from 'laikacms/storage-api';
import { FileSystemStorageRepository } from 'laikacms/storage-fs';
import { markdownSerializer } from 'laikacms/storage-serializers-markdown';

const repo = new FileSystemStorageRepository('./content', { md: markdownSerializer }, 'md');
const api = buildJsonApi({ repo });

serve({ fetch: api.fetch, port: 3000 });

Auth and CORS

buildJsonApi has no built-in authentication or CORS handling. Add them as middleware around api.fetch at the framework level.

Example with Hono:

typescript
import { Hono } from 'hono';
import { bearerAuth } from 'hono/bearer-auth';
import { cors } from 'hono/cors';
import { buildJsonApi } from 'laikacms/storage-api';
import { FileSystemStorageRepository } from 'laikacms/storage-fs';
import { markdownSerializer } from 'laikacms/storage-serializers-markdown';

const repo = new FileSystemStorageRepository('./content', { md: markdownSerializer }, 'md');
const api = buildJsonApi({ repo });

const app = new Hono();
app.use('*', cors({ origin: 'https://your-frontend.example.com' }));
app.use('*', bearerAuth({ token: process.env.API_TOKEN! }));
app.all('*', c => api.fetch(c.req.raw));

Logger

Pass a logger option to buildJsonApi to control log verbosity. Any object implementing Pick<Console, 'error' | 'warn' | 'info' | 'debug'> works:

typescript
const api = buildJsonApi({ repo, logger: console });

Pass a no-op or filtered logger to suppress output:

typescript
const api = buildJsonApi({
  repo,
  logger: { error: console.error, warn: console.warn, info: () => {}, debug: () => {} },
});

Security Checklist

  • [ ] HTTPS only
  • [ ] CORS configured at the framework/middleware level (not built in to buildJsonApi)
  • [ ] Rate limiting enabled
  • [ ] Authentication added via middleware (not built in to buildJsonApi)
  • [ ] Secrets in environment variables

Released under the MIT License.