Skip to content

Vanilla JS

ACMS works with plain JavaScript — no framework required. This guide covers using ACMS in vanilla JS projects, static sites, and any environment where you write plain HTML and JavaScript.

Terminal window
npm install @useacms/client @useacms/cli

Or use a CDN for quick prototyping:

<script type="module">
import { acms } from 'https://esm.sh/@useacms/client';
</script>
<!DOCTYPE html>
<html>
<body>
<h1 id="title"></h1>
<p id="subtitle"></p>
<script type="module">
import { acms } from '@useacms/client';
document.getElementById('title').textContent = acms.hero.title;
document.getElementById('subtitle').textContent = acms.hero.subtitle;
</script>
</body>
</html>

If you’re using a bundler (Vite, webpack, Parcel, esbuild):

main.js
import { acms } from '@useacms/client';
document.querySelector('.hero-title').textContent = acms.hero.title;
document.querySelector('.hero-subtitle').textContent = acms.hero.subtitle;
document.querySelector('.cta-link').href = acms.hero.ctaLink;
document.querySelector('.cta-link').textContent = acms.hero.ctaText;

Subscribe to content changes for live updates:

import { acms, subscribe } from '@useacms/client';
function render() {
document.getElementById('title').textContent = acms.hero.title;
document.getElementById('subtitle').textContent = acms.hero.subtitle;
}
// Initial render
render();
// Re-render on content changes
subscribe(() => {
render();
});

Create acms.config.ts (or .js) in your project root:

import { defineConfig } from '@useacms/client';
import { localFile, githubGist } from '@useacms/cli/adapters';
export default defineConfig({
dev: localFile({ path: './acms.json' }),
production: githubGist({
token: process.env.GITHUB_TOKEN,
gistId: process.env.GIST_ID,
}),
});
Terminal window
# Terminal 1: ACMS dev server
acms dev
# Terminal 2: Your dev server (Vite, live-server, etc.)
npx vite # or any static file server
import { acms } from '@useacms/client';
document.querySelector('h1').textContent = acms.hero.title;
document.querySelector('img.logo').src = acms.brand.logo;
document.querySelector('a.cta').href = acms.hero.ctaLink;
const list = document.getElementById('features');
acms.features.forEach((feature) => {
const li = document.createElement('li');
li.textContent = feature;
list.appendChild(li);
});
const banner = document.getElementById('banner');
banner.style.display = acms.banner.visible ? 'block' : 'none';
banner.querySelector('p').textContent = acms.banner.message;

Use template literals for building HTML strings:

import { acms } from '@useacms/client';
document.getElementById('app').innerHTML = `
<header>
<h1>${acms.hero.title}</h1>
<p>${acms.hero.subtitle}</p>
</header>
<main>
<ul>
${acms.features.map((f) => `<li>${f}</li>`).join('')}
</ul>
</main>
<footer>
<p>${acms.footer.copyright}</p>
</footer>
`;

ACMS works well with custom elements:

import { acms, subscribe } from '@useacms/client';
class AcmsText extends HTMLElement {
connectedCallback() {
const path = this.getAttribute('path');
this.render(path);
subscribe(() => this.render(path));
}
render(path) {
const keys = path.split('.');
let value = acms;
for (const key of keys) {
value = value[key];
}
this.textContent = value;
}
}
customElements.define('acms-text', AcmsText);
<h1><acms-text path="hero.title"></acms-text></h1>
<p><acms-text path="hero.subtitle"></acms-text></p>