Skip to content
AtMyApp Docs
Go to AtMyApp
Open with AI

Connect a JavaScript website

Use @atmyapp/core in any JavaScript or TypeScript project. Your framework owns the HTML; AtMyApp supplies the editable content. If you use Astro, follow the Astro setup for automatic configuration, metadata, previews, and forms.

Create a project in AtMyApp and configure its content source in Project Setup. Copy the project API URL and a public website API key. You also need a CLI token to upload your schema.

These credentials have different roles:

Value Used for Where it belongs
Project API URL Identifies the project and environment Website configuration; include the complete project path
Public website API key SDK reads and permitted website operations Server, build process, or browser
CLI token Project administration and schema uploads Local CLI session or protected CI configuration
Preview key Access to a particular unpublished preview That preview request; never a shared production default

The website API key is public by design. A CLI token is not a replacement for it. Use the URLs provided by your environment rather than guessing the hostname.

In your existing website project:

Terminal window
npm install @atmyapp/core @atmyapp/structure
npm install --save-dev @atmyapp/cli

Use a module-aware bundler for browser code. A bare import such as @atmyapp/core is resolved by your build tool, not by a plain browser script tag. This guide does not require React, Vue, or another UI framework.

Terminal window
npx atmyapp use --token cli_YOUR_TOKEN --url YOUR_PROJECT_API_URL

Replace both placeholders. Run this in the website directory. The session is stored in .ama/session.json; add that file to .gitignore. See CLI workflow for initialization and upload commands.

Create atmyapp.schema.ts in the project root:

import { defineSchema, defineDocument, s } from "@atmyapp/structure";
export default defineSchema({
definitions: {
home: defineDocument({
path: "home.json",
description: "Text shown at the top of the homepage.",
fields: {
headline: s.string({
min: 1,
max: 100,
description: "The main heading.",
}),
introduction: s.string({ format: "long", optional: true }),
},
}),
},
});

The key home identifies the definition. home.json is its content path. Neither is the URL of your homepage. Choose stable identifiers; changes to these names can affect existing content and code.

Terminal window
npx atmyapp migrate --dry-run --verbose
npx atmyapp migrate

The first command lets you inspect the generated structure. The second uploads it to the connected project. A schema describes data; it does not populate every document with real website copy. Create the homepage content in AtMyApp and publish it before testing a normal production read.

Use this content shape:

{
"headline": "A website your team can update",
"introduction": "Edit the content while keeping your custom design."
}

For existing content files, see CLI uploads. Keep your schema in source control alongside the code that renders it.

// src/atmyapp.ts (schema lives in the project root)
import { createAtMyAppClient } from "@atmyapp/core";
import schema from "../atmyapp.schema";
export const ama = createAtMyAppClient({
baseUrl: "YOUR_PROJECT_API_URL",
apiKey: "YOUR_PUBLIC_WEBSITE_API_KEY",
schema,
errorPolicy: "throw",
});

Replace the placeholders with your project values. Passing the actual schema enables typed definition names and returned content. Importing types alone does not enable runtime schema-aware helpers.

Core does not automatically read environment variables. Map your framework’s configuration into these options. For Node, use process.env; for Vite browser code, use its public import.meta.env configuration. Astro’s integration handles environment lookup for you.

For a browser page, add a heading and a status message:

<h1 id="headline">Welcome</h1>
<p id="introduction"></p>
<p id="content-status" role="status"></p>

Then load this code through your site’s bundler:

import { ama } from "./atmyapp";
async function renderHome() {
const status = document.querySelector("#content-status")!;
try {
const home = await ama.storage.getValue("home");
document.querySelector("#headline")!.textContent = home.headline;
document.querySelector("#introduction")!.textContent =
home.introduction ?? "";
status.textContent = "";
} catch {
status.textContent =
"Content is temporarily unavailable. Please try again.";
}
}
void renderHome();

getValue() returns the document fields directly. get() returns a wrapper; getFromPath() reads a raw path without an inferred shape. Use textContent for plain text. Markdown and MDX require a renderer and an explicit sanitization/component policy in your application.

Approach Where the SDK runs When published edits appear
Browser rendering In the visitor’s browser On a new read, subject to caching
Server rendering In your request handler On a new request, subject to your caches
Static generation During your build After a successful rebuild and deployment

For static generation, await ama.storage.getValue('home') inside your framework’s build loader and pass the returned fields into its template. Keep errorPolicy: 'throw' so a failed read can fail the build instead of producing empty pages. Configure a rebuild workflow; changing content cannot rewrite already generated HTML.

For server rendering, create preview-aware clients inside each request. Never put a preview key into a process-global client:

import { createAtMyAppClient } from "@atmyapp/core";
import schema from "../atmyapp.schema";
export function clientForRequest(request: Request) {
const previewKey =
new URL(request.url).searchParams.get("amaPreviewKey") || undefined;
return createAtMyAppClient({
apiKey: "YOUR_PUBLIC_WEBSITE_API_KEY",
baseUrl: "YOUR_PROJECT_API_URL",
schema,
previewKey,
mode: previewKey ? "priority" : "client",
errorPolicy: "throw",
});
}

Only enable preview handling on routes intended to render previews. Do not cache preview HTML publicly or silently turn a failed preview into published content. A static production page does not become a live preview merely because a query parameter was added. See Astro previews for the integrated implementation.

Read a known published document, change it in AtMyApp, and verify the update through your chosen rendering path. Test unavailable content, an invalid API key, and an expired preview. Add optional diagnostics when you want an inspectable report.

Continue with schema design, forms, and the client handoff.