Skip to content

Releases: micacms/mica

v0.16.0

Choose a tag to compare

@github-actions github-actions released this 27 Oct 17:52

This version adds localization (i18n). One entry holds the text of each
language of a multilingual website, and the editor shows one language at a
time. Editors and agents can find what still needs a translation.

Added

  • Localized fields. A site declares its locales, defaultLocale and
    fallback, with the names of Astro's i18n. A field with localized: true
    stores a value for each locale in the same entry, and rich text has one file
    for each locale, such as body.de.mdoc. required applies to the default
    locale, and a missing translation never stops Save or Publish (ADR 42).
  • localize(site, name, data, locale) in @micacms/astro gives an entry
    or a singleton in one locale. A missing value falls back to fallback, then
    to the default locale. localized: { fallback: false } keeps it empty.
  • The locale in a page's URL. A url can name {locale}, such as
    /{locale}/news/{id}, with prefixDefaultLocale as in Astro. The preview,
    "Open on website" and the URL under the ID field show the page of the form's
    language, and the live preview's page changes the form's language. A
    localized id() must be unique in each locale: mica check and Publish
    report a duplicate (ADR 43).
  • A language switcher in the header of a form, with the number of missing
    translations of each language. A button beside each localized field shows
    its other languages, can use one of them, and marks a missing translation.
  • Find missing translations. The list of a collection shows the missing
    translations of each entry, and a filter shows the entries that miss one
    language. The Overview lists them for each language. The MCP tool
    list_entries gives missingTranslations and takes missing, and
    mica check lists them as information.
  • localesOf(site, name, data) in @micacms/astro gives the locales that
    an entry has its own text in, for getStaticPaths, lists, the sitemap and
    hreflang (ADR 44).
  • Links in rich text can get the address in the page's locale, with the
    link option of renderRichText.

Changed

  • The header of a form is tidier: the status is below the title, and the
    entry's folder is below the form.
  • A model with locales needs this version of Mica. Upgrade @micacms/editor
    and the image together with @micacms/astro. A site without locales writes
    the same .mica/schema.json as before.

v0.15.0

Choose a tag to compare

@github-actions github-actions released this 26 Oct 14:29

This version calls an entry's identity its ID, and the address of its page its
URL. A URL can have more parts, such as /{activity}/{id}. It also fixes an issue with thousands of changes on the Publish page, a busy port for
the preview, and relations to one entry.

Breaking

  • slug() is now id(). An entry's identity is its ID: one part, the name
    of its folder, and what a relation stores. In the model, change slug() to
    id(), and {slug} in a url to {id}. The content files stay as they are,
    unless you also rename the key of the field. related() and relatedAll()
    take IDs. The names in @micacms/core follow: idField, toId,
    isValidId, IdField, and id in ContentEntry and the other types
    (ADR 41).
  • The admin HTTP API and the MCP tools say id in place of slug, such as
    get_entry({ collection, id }) and reorder_entries({ ids }).

Added

  • A URL with more parts. A collection's url can name other fields beside
    {id}, such as /{activity}/{id}: a select or a relation to one entry, or a
    date without a time, each as a whole part of the path. The editor links to
    such a page with the entry's saved values, and the preview finds the entry of
    the page.
  • The page's URL in the editor, under the ID field, in the list of a
    collection and in the relation pickers. Change ID names the old and the new
    URL of the page.
  • Change for a relation to one entry. The field shows the chosen entry with
    Edit, Change and Remove. Change opens a dialog to find another entry. A row of
    a list can take its title from a relation.

Changed

  • @micacms/astro no longer has the peer dependency @astrojs/compiler-rs.
    The preview takes the parser that the site's Astro brings, and checks at the
    start that it places the fields right. With Astro 7.0 to 7.2, dates, numbers
    and options in the preview cannot be clicked, and the dev server says so.

Fixed

  • The Publish page with thousands of changes no longer gets "Too many
    requests". It loads a comparison when its row comes near the screen, in
    batches.
  • mica start --preview with a busy port reads the address that
    astro dev prints, so the preview no longer shows another website or waits
    for ever. A preview whose address Mica cannot confirm shows "Preview not
    confirmed", with the reason.
  • The preview no longer stays "starting" when the home page takes more than a
    second to render.
  • The list of a relation field is no longer cut off in a list row or a group.

v0.14.0

Choose a tag to compare

@github-actions github-actions released this 25 Oct 18:12

This version names the website in the editor, says how its preview is, and
shows what went wrong, without a shell on the server.

Added

  • The website's name. defineSite({ label }) names the website for its
    editors, with 60 characters at most. The top of the editor's menu shows it,
    with the address of the published website from MICA_SITE_URL, and a click
    on it opens the Overview. An older Mica ignores the label.
  • The state of the preview at the top of the menu: Preview live, starting,
    stopped or off. While it is live, a click opens it. A form with a page says
    why the page is not there yet.
  • Recent problems on the System page. It lists the last warnings and
    errors since Mica started, kept in memory only, with email addresses hidden,
    and a Preview section with the state of the preview and its last lines.
    "Copy report" adds them.
  • The preview image reports its state on port 4380 inside the network, so
    that the self-hosted editor knows when the preview copies, installs, starts
    or failed, and why. An image of your own does not need it.
  • Ready to run on demand. Before the self-hosted Mica stops, it tries once
    more to push a publication that waits, and after a start of both, the
    preview waits for Mica's first sync (ADR 39).

Changed

  • The whole first cell of an entry list opens the entry.

Fixed

  • The local editor reads MICA_SITE_URL, as the docs say.
  • The local editor keeps its preview when a second dev server of the same
    content root stops.

v0.13.0

Choose a tag to compare

@github-actions github-actions released this 24 Oct 13:45

This version adds the live preview: the real page of the website beside the
form, with the drafts in it, in the local and in the self-hosted editor. The
editor also saves by itself.

Added

  • The live preview. The editor shows the page of an entry beside its form,
    with the drafts in it, about a second after you stop typing. A click on a
    text, a paragraph, an image, a date or an option in the page opens its field,
    and a related entry, such as the author of an article, opens over the current
    form. Unpublished changes have an outline. Add micaPreview() from
    @micacms/astro/preview to astro.config; the templates do not change.
  • mica start --preview starts the editor and the website's
    astro dev with one command, also on Windows. The dev server stops with the
    editor.
  • The live preview in the self-hosted editor. The image
    ghcr.io/micacms/preview runs the website's dev server on the drafts of
    Mica's clone, in a container of its own. Mica lets only signed-in editors in,
    on the name preview.<the editor's name>. MICA_PREVIEW_UPSTREAM turns it
    on. See "Add the live preview" in the self-hosting guide.
  • The editor saves by itself: after a short pause in typing, when you leave
    a field, and when a form closes. A new entry has a Create button. A new URL
    waits for Change URL, which can also update the links in other entries.

Changed

  • @micacms/astro has a new peer dependency, @astrojs/compiler-rs, which
    Astro 7 installs. The preview uses it to find dates, numbers and options in
    the templates.
  • The sidebar and the page header stay in place while the page scrolls.
    Settings show their description below the title.
  • The editor's Content-Security-Policy allows frames from the origins of the
    live preview, and from no other.

Fixed

  • The local editor finds the dev server also when Astro takes another port,
    with micaPreview(). The dev server deletes its note for the editor also on
    Ctrl+C.
  • A content root that cannot be written, such as the one of the self-hosted
    preview, gets a warning for the index of a reference set, and the site builds.

v0.12.0

Choose a tag to compare

@github-actions github-actions released this 19 Oct 07:27

This version adds no features. It tightens sign-in, makes failures clear, and
tests much more: Windows, macOS and Node.js 26, the packed packages in a new
Astro project, and the local editor in a browser.

Breaking

  • A domain rule with Google needs the Workspace domain. With
    MICA_ADMIT_DOMAINS and Google, the account's hd claim must be an admitted
    domain. A personal Google account with a company address is no longer
    admitted: add it to MICA_ADMIT_EMAILS. Put the primary domain of your
    Workspace in MICA_ADMIT_DOMAINS. Editors who sign in with Google through a
    domain rule must sign in again after the upgrade.

Changed

  • The consent page for an agent accepts Allow only one second after it
    opens, so that a click hidden behind a pop-up window cannot allow an agent.
    The check of a client document refuses more private IPv6 ranges, and a
    loopback redirect address must not have a fragment or a user name.
  • A broken entry file no longer hides its collection. The list shows the
    other entries and names each file that Mica cannot read.
  • A full or read-only disk gives a clear message that asks the person who
    runs Mica to act, and an error in the log, also for an MCP tool.
  • A server failure shows its reference in the editor, which the log names
    too.
  • The page "Versions and support" on micacms.com states what semantic
    versioning covers from 1.0, and which versions Mica supports.

Fixed

  • Windows: the content root can be given in any spelling, such as
    D:/site/content.

v0.11.0

Choose a tag to compare

@github-actions github-actions released this 18 Oct 06:19

Mica works for larger sites. Git LFS holds the photos, and the content can live
in a repository of its own, as a Git submodule of the website. A media field
takes GPX, KML, GeoJSON, ZIP and CSV files beside images and PDF. A coordinates
field can show a map, and the website shows the place with <LocationMap> from
the new @micacms/astro/components. A relation can point to reference data
that Mica does not edit, such as thousands of place names from a file. Images in
rich text are optimized by Astro. An entry links to its page on the website,
and the local editor shows a preview of the saved changes while astro dev
runs. Large galleries fill with a drop. The editor loads rich text only where a
form has it, and a save never leaves out fields of a newer model.

Read Breaking before upgrading from 0.10: each website changes its calls of
renderRichText.

Breaking

  • renderRichText and transformRichText are async, and take the entry's
    data:
    await renderRichText(entry.data.body, entry.data). They find the
    images of the entry themselves, and Astro's image service optimizes each one
    (srcset and sizes in 480, 800, 1200 and 1600 px as WebP, up to the
    original). { optimize: false } writes the original; { config } moves to
    the third argument. A site needs Astro's image service, sharp, as for
    <Image>. Without await, set:html still renders, but a check such as
    {html && …} is always true (@micacms/astro).
  • _mica holds only position and images. Use entry.id and the
    collection's name instead of _mica.id, _mica.slug and
    _mica.collection. _mica.position is now the editor's order, the
    collection's defaultSort included (@micacms/astro).
  • In CI, the build checks .mica/schema.json and writes nothing. A build
    with CI set fails when the committed model is not the one in the code, and
    the same for the index of each reference set. Run astro dev or
    astro build locally and commit the files (@micacms/astro).
  • A model with a relation to a reference set cannot be read by Mica 0.10
    and older. Upgrade every Mica that edits the site (@micacms/core).
  • @micacms/runtime exports less. 21 exports that nothing used are
    removed, classifyPath moves to @micacms/core as ownerOfPath, the owner
    policy of createRuntimeContext is required, and MICA_LOCAL_PUBLISH and
    the developer policy move to the local editor (@micacms/runtime).

Added

  • Git LFS for media under the content root. The site owner chooses the
    paths in .gitattributes. The image has git-lfs; clone, sync and Publish
    fetch and push the LFS files, and MICA_REPOSITORY_LFS_URL sets another LFS
    address. The local editor stops at start when the content uses LFS and Git
    LFS is not set up (@micacms/runtime, @micacms/editor, the image).
  • Content in a Git submodule. Mica works in the repository that holds the
    content root, never in the website repository. On a detached HEAD, Publish
    waits, and the banner and the Publish page give the command that checks out
    the branch (@micacms/runtime, @micacms/editor).
  • More file types. A media field's accept takes a list, such as
    ["gpx", "kml"]. Mica knows images, PDF, GPX, KML, GeoJSON, ZIP and CSV, and
    checks each from its bytes. Files can be dropped on a media field, and an
    upload of many files shows its progress and goes on after a failure.
    mediaFile(site, path) gives the file on disk for the build
    (@micacms/core, @micacms/runtime, @micacms/editor, @micacms/mcp,
    @micacms/astro).
  • A map for coordinates. coordinates({ map: "liberty" }) shows an
    OpenFreeMap map in the editor, and { style, hosts } a style of your own.
    The value stores the zoom: { lat, lng, zoom }. The Content-Security-Policy
    allows the map's hosts only when the model has a map (@micacms/core,
    @micacms/runtime, @micacms/editor).
  • @micacms/astro/components with <LocationMap>: a map of a coordinates
    value, without styles of its own. It needs maplibre-gl on the site.
    mapView() gives the same view for a site's own map (@micacms/astro).
  • Reference data. defineSite({ references }) with referenceSet()
    declares a JSON or CSV file of the website that Mica never edits. A relation
    can point to it. The build writes .mica/references/<name>.json; the picker
    searches it, and Publish, mica check and the build check each id. The MCP
    tool find_reference_items searches it (@micacms/core, @micacms/astro,
    @micacms/runtime, @micacms/editor, @micacms/mcp).
  • "Open on website" and Preview. collection({ url: "/news/{slug}" }) and
    singleton({ url: "/about" }) with MICA_SITE_URL link an entry to its
    page, and Publish links to the pages it published. The local editor shows
    Preview while astro dev runs: the page with the saved changes, before
    Publish (@micacms/core, @micacms/runtime, @micacms/editor,
    @micacms/astro).
  • Website helpers. getSingleton(site, name) reads a singleton with its
    types, and inEditorOrder sorts a collection in the editor's order
    (@micacms/astro).

Changed

  • Rich text is lighter. Tiptap and Markdoc load only for a form with a
    rich-text field: the chunk that every form loads goes from 232 kB to 42 kB
    gzip. A field decides at load whether it is read-only, and the editor refuses
    an edit it cannot keep. Typing converts the text when you pause, and Save
    always sends the current text (@micacms/editor).
  • Errors have their own status. 409 for a conflict, 422 for an invalid
    value or a file that cannot be read, 404 for an unknown collection or
    singleton, 400 for the rest. A page that could not load says so, with Try
    again, and never shows an empty list (@micacms/runtime, @micacms/editor).
  • One rule for the links of a document. Relations, media, and the images
    and links in rich text are read the same way by Mica, the build and
    mica check (@micacms/core, @micacms/runtime).
  • Entries and settings share one form, so a save and a conflict work the
    same in both (@micacms/editor).

Fixed

  • A save no longer leaves out the fields of a newer model. While a newer
    .mica/schema.json cannot be read, every write is refused with a 409 that
    says why, in the editor and over MCP; reads go on (@micacms/runtime,
    @micacms/editor, @micacms/mcp).
  • Publish takes along a new file that rich text links to, such as a new
    PDF in the shared folder, and refuses to publish the deletion of a file that
    rich text links to, or of an entry whose media another entry uses
    (@micacms/runtime).
  • A {% typed in rich text stays text. It became a tag on the website and
    made the field read-only (@micacms/editor).
  • A save that worked no longer says that it failed when only reading the
    saved version back failed (@micacms/editor).
  • Old temporary upload files are removed at the start of the local editor
    (@micacms/editor).

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 06:33
7db5d93

Coding agents can edit the content. Claude Code, Cursor, VS Code and other
clients of the Model Context Protocol (MCP) read the content model and save
content through a fixed set of tools. They follow the rules of the editor: Mica
checks every value, every save sends the revision that the agent read, and a
save is a draft. A person publishes the drafts, unless you let agents publish
too. On your own machine, npx mica start serves the tools at /mcp, and
npx mica mcp serves them over stdio. A self-hosted Mica serves them with
MICA_MCP=true: each person signs in as for the editor and allows each agent.

Nothing to do before upgrading from 0.9.

Added

  • The Mica tools for agents. describe_model, list_entries,
    get_entry, get_singleton, find_references, list_media,
    save_entry, save_singleton, delete_entry, reorder_entries,
    upload_media, get_changes, discard_changes, and publish only when it
    is allowed. Their names and inputs are public from 1.0 (@micacms/mcp,
    @micacms/editor, @micacms/runtime).
  • npx mica mcp [content dir] serves the tools over stdio, for an agent
    that starts Mica itself. npx mica start serves them at /mcp, and its
    banner shows how to add Mica to an agent. --allow-publish and
    MICA_MCP_PUBLISH=true give agents publish (@micacms/editor).
  • Agents on a self-hosted Mica. MICA_MCP=true serves /mcp in the
    image. Mica is the OAuth server of the endpoint: the person signs in with
    the editor's OIDC flow, the MICA_ADMIT_* rules apply, and a consent page
    allows one agent. Mica stores no clients and no tokens; access ends after
    MICA_SESSION_TTL_HOURS. With MICA_MCP_PUBLISH=true, a person can also
    allow an agent to publish (@micacms/runtime, the image).
  • @micacms/mcp, a new internal package. It is published because
    @micacms/editor installs it, and it is pinned exactly (@micacms/mcp).

Changed

  • Internal: one publish and one upload for every client. The editor's
    routes and the agent tools use the same services, so they refuse and
    validate in the same way (@micacms/runtime).

A review of the whole project, and the changes that came from it. The content
format is simpler: one folder for each entry and each singleton, rich text in a
repeater row named by the row's key, and a save that keeps what the model does
not declare. A specification describes the format, and tests check it against
fixtures. @micacms/core exports a smaller public API, and four packages are
published. Publish, Discard, Delete and Reorder check the revision that the
editor saw, so a colleague's later save shows as a conflict. The self-hosted
image finds its content root, repairs its clone after a force push, and reports
problems in /ready. The budget tests use the 1.0 target: 1,000 entries in a
collection, 5,000 files and 5 editors. The editor has a new look with a dark
mode.

Read Breaking before upgrading from 0.8. This release has no migration: move
the content files to the new layout by hand, or start again from your Git
history.

Breaking

  • One folder for each entry and each singleton. An entry is
    <collection>/<slug>/index.json, a singleton is <name>/index.json, and
    media is a reserved name. The manifest records no layout.
    mica migrate-layout is removed. Removed: collectionEntryPath,
    singletonPath, entryLayout, deriveLayout, recordLayout,
    misplacedFiles and LayoutError. New: entryFolder and
    entryDataPath (@micacms/core, @micacms/astro, @micacms/editor,
    @micacms/runtime).
  • Rich text in a repeater row is stored in a file named by the row's key,
    such as sections.k3f9a2.body.mdoc, and a row with rich text has a _key
    in the JSON. A new order of the rows changes only index.json
    (@micacms/core).
  • A save keeps what the model does not declare, the keys and the .mdoc
    files. A default fills a field only in a new entry; a read fills a missing
    value with its empty value. withDefaults is now withEmptyValues, and
    serializeEntry takes the stored JSON (@micacms/core, @micacms/runtime).
  • Stricter model rules. The model refuses two names that differ only in
    case, a slugField that is not a slug, a lower bound above an upper one, a
    default that is not a valid value, and a text pattern that repeats a group
    with a repeat inside, such as (a+)+. An unknown field option stops the
    build, and makes its collection read-only in an older editor
    (@micacms/core, @micacms/astro).
  • The public API of @micacms/core is smaller. The main entry point has
    the model, validation, the content format, the readers and the model file.
    Removed: getCollection, getSingleton, uniqueSlug and toIssues.
  • Four published packages: @micacms/core, @micacms/astro,
    @micacms/editor (with the built editor UI) and @micacms/runtime.
    @micacms/editor-ui and @micacms/auth-oidc are no longer published.
  • The content root is set in one place, defineSite({ root }).
    micaCollections has no root option (@micacms/astro).
  • Self-hosted configuration:
    • MICA_REPOSITORY_ROOT is removed. The image finds the content root by its
      .mica/schema.json; MICA_CONTENT_PATH names it only when the repository
      has more than one. The top of the repository cannot be the content root.
    • MICA_PUBLIC_URL and MICA_SESSION_SECRET are always required.
      MICA_PUBLIC_URL must be an origin without a path.
    • NODE_ENV changes nothing. Plain HTTP is allowed only for an address on
      this machine.
    • MICA_SIGNIN_WINDOW_MS is now MICA_SIGNIN_WINDOW_MINUTES.
    • MICA_ADMIN_ORIGINS and MICA_ADMIN_DIR are local-editor settings only.
  • /ready has the status degraded (still HTTP 200) when something needs
    a person, one reason for each problem, and lastSyncAt.
    restart_required is removed; lfs_refused, model_unreadable,
    pending_push, conflict and others are new (@micacms/runtime).
  • The CLI. Each command takes only its own options, and a path is always
    the content root. mica import takes --collection <name> in place of names.
    check and import exit with 78 without a readable model
    (@micacms/editor).
  • Uploads are one file for each request, sent as the request body.
    Internal: ContentFiles has readHead, readStream and receive in place
    of readBinary (@micacms/runtime, @micacms/editor).

Added

  • A specification of the content format in docs/content-format.md, with
    fixtures that a test reads and writes back byte for byte (@micacms/core).
  • A new look for the editor: green actions, a light sidebar, the
    Instrument Sans and IBM Plex Mono fonts, status labels with a coloured dot,
    and a dark mode. Under Appearance, an editor chooses light, dark or the mode
    of the system (@micacms/editor).
  • One way to change an order for the entries of a collection, the items of
    a list, the chosen entries of a relation and the files of a media field: a
    handle drags an item or moves it with the keyboard, and arrow buttons move it
    one step (@micacms/editor).
  • The self-hosted image:
    • finds its content root in the clone;
    • follows a rewritten branch (a force push or a reset) and a new repository
      URL, and keeps the drafts as conflicts until an editor chooses;
    • starts with the model in its clone and syncs in the background, and holds
      a new version that it cannot use (LFS under the content root, or a model
      that it cannot read);
    • runs only once for each data volume, with a lease, and finishes the work
      that a stop or a crash interrupted;
    • reads MICA_SESSION_SECRET_FILE, MICA_OIDC_CLIENT_SECRET_FILE and
      MICA_REPOSITORY_TOKEN_FILE; the token file is read for each Git call;
    • has a compact command that makes the clone small again;
    • check also tests the identity provider, shows the redirect URI, and
      checks the data volume and the clone.
  • The CLI finds the content root by its .mica/schema.json when no path
    is given (@micacms/editor).
  • In astro dev, a change to src/mica.ts logs how to load the new model
    (@micacms/astro).
  • New recipe remove-field.mjs (@micacms/core).

Changed

  • Publish, Discard, Delete and Reorder check the revision that the editor
    saw.
    A colleague's later save is a conflict, not lost or published unseen
    (@micacms/runtime, @micacms/editor).
  • Faster at the 1.0 target. Publish with a deletion reads the unchanged
    files from the working tree, not one Git process for each file. The budget
    tests use 1,000 entries in one collection, 5,000 files and five editors at
    the same time (@micacms/runtime).
  • No whole media file in memory. An upload streams to disk, the file route
    streams, a revision is a cached, streamed hash, and a URL change copies the
    media on disk (@micacms/runtime).
  • A slow network does not block the start, the sync or Publish: a sync
    skips its turn while one runs, a stalled transfer stops, and Git has
    settings for large repositories with many images.
  • mica init writes the starter's model, the same one as
    examples/starter and the getting-started page (@micacms/editor).
  • The release workflow builds without write rights and publishes from a
    separate job; dependencies are audited every week and updated every month.

Fixed

  • Security: the content files refuse a symbolic link out of the content
    root and the .git folder; a route slug is one folder name; a media()
    value stays inside the content root; a name such as constructor is not a
    collection; sign-out removes the unsaved form values that the tab kept
    (@micacms/core, @micacms/runtime, @micacms/editor, @micacms/astro).
  • The first Publish of a new project names git push -u origin HEAD
    when the branch has no upstream (@micacms/runtime).
  • astro add no longe...
Read more

v0.9.0

Choose a tag to compare

@amuedespacher amuedespacher released this 14 Oct 12:31

A review of the whole project, and the changes that came from it. The content
format is simpler: one folder for each entry and each singleton, rich text in a
repeater row named by the row's key, and a save that keeps what the model does
not declare. A specification describes the format, and tests check it against
fixtures. @micacms/core exports a smaller public API, and four packages are
published. Publish, Discard, Delete and Reorder check the revision that the
editor saw, so a colleague's later save shows as a conflict. The self-hosted
image finds its content root, repairs its clone after a force push, and reports
problems in /ready. The budget tests use the 1.0 target: 1,000 entries in a
collection, 5,000 files and 5 editors. The editor has a new look with a dark
mode.

Read Breaking before upgrading from 0.8. This release has no migration: move
the content files to the new layout by hand, or start again from your Git
history.

Breaking

  • One folder for each entry and each singleton. An entry is
    <collection>/<slug>/index.json, a singleton is <name>/index.json, and
    media is a reserved name. The manifest records no layout.
    mica migrate-layout is removed. Removed: collectionEntryPath,
    singletonPath, entryLayout, deriveLayout, recordLayout,
    misplacedFiles and LayoutError. New: entryFolder and
    entryDataPath (@micacms/core, @micacms/astro, @micacms/editor,
    @micacms/runtime).
  • Rich text in a repeater row is stored in a file named by the row's key,
    such as sections.k3f9a2.body.mdoc, and a row with rich text has a _key
    in the JSON. A new order of the rows changes only index.json
    (@micacms/core).
  • A save keeps what the model does not declare, the keys and the .mdoc
    files. A default fills a field only in a new entry; a read fills a missing
    value with its empty value. withDefaults is now withEmptyValues, and
    serializeEntry takes the stored JSON (@micacms/core, @micacms/runtime).
  • Stricter model rules. The model refuses two names that differ only in
    case, a slugField that is not a slug, a lower bound above an upper one, a
    default that is not a valid value, and a text pattern that repeats a group
    with a repeat inside, such as (a+)+. An unknown field option stops the
    build, and makes its collection read-only in an older editor
    (@micacms/core, @micacms/astro).
  • The public API of @micacms/core is smaller. The main entry point has
    the model, validation, the content format, the readers and the model file.
    Removed: getCollection, getSingleton, uniqueSlug and toIssues.
  • Four published packages: @micacms/core, @micacms/astro,
    @micacms/editor (with the built editor UI) and @micacms/runtime.
    @micacms/editor-ui and @micacms/auth-oidc are no longer published.
  • The content root is set in one place, defineSite({ root }).
    micaCollections has no root option (@micacms/astro).
  • Self-hosted configuration:
    • MICA_REPOSITORY_ROOT is removed. The image finds the content root by its
      .mica/schema.json; MICA_CONTENT_PATH names it only when the repository
      has more than one. The top of the repository cannot be the content root.
    • MICA_PUBLIC_URL and MICA_SESSION_SECRET are always required.
      MICA_PUBLIC_URL must be an origin without a path.
    • NODE_ENV changes nothing. Plain HTTP is allowed only for an address on
      this machine.
    • MICA_SIGNIN_WINDOW_MS is now MICA_SIGNIN_WINDOW_MINUTES.
    • MICA_ADMIN_ORIGINS and MICA_ADMIN_DIR are local-editor settings only.
  • /ready has the status degraded (still HTTP 200) when something needs
    a person, one reason for each problem, and lastSyncAt.
    restart_required is removed; lfs_refused, model_unreadable,
    pending_push, conflict and others are new (@micacms/runtime).
  • The CLI. Each command takes only its own options, and a path is always
    the content root. mica import takes --collection <name> in place of names.
    check and import exit with 78 without a readable model
    (@micacms/editor).
  • Uploads are one file for each request, sent as the request body.
    Internal: ContentFiles has readHead, readStream and receive in place
    of readBinary (@micacms/runtime, @micacms/editor).

Added

  • A specification of the content format in docs/content-format.md, with
    fixtures that a test reads and writes back byte for byte (@micacms/core).
  • A new look for the editor: green actions, a light sidebar, the
    Instrument Sans and IBM Plex Mono fonts, status labels with a coloured dot,
    and a dark mode. Under Appearance, an editor chooses light, dark or the mode
    of the system (@micacms/editor).
  • One way to change an order for the entries of a collection, the items of
    a list, the chosen entries of a relation and the files of a media field: a
    handle drags an item or moves it with the keyboard, and arrow buttons move it
    one step (@micacms/editor).
  • The self-hosted image:
    • finds its content root in the clone;
    • follows a rewritten branch (a force push or a reset) and a new repository
      URL, and keeps the drafts as conflicts until an editor chooses;
    • starts with the model in its clone and syncs in the background, and holds
      a new version that it cannot use (LFS under the content root, or a model
      that it cannot read);
    • runs only once for each data volume, with a lease, and finishes the work
      that a stop or a crash interrupted;
    • reads MICA_SESSION_SECRET_FILE, MICA_OIDC_CLIENT_SECRET_FILE and
      MICA_REPOSITORY_TOKEN_FILE; the token file is read for each Git call;
    • has a compact command that makes the clone small again;
    • check also tests the identity provider, shows the redirect URI, and
      checks the data volume and the clone.
  • The CLI finds the content root by its .mica/schema.json when no path
    is given (@micacms/editor).
  • In astro dev, a change to src/mica.ts logs how to load the new model
    (@micacms/astro).
  • New recipe remove-field.mjs (@micacms/core).

Changed

  • Publish, Discard, Delete and Reorder check the revision that the editor
    saw.
    A colleague's later save is a conflict, not lost or published unseen
    (@micacms/runtime, @micacms/editor).
  • Faster at the 1.0 target. Publish with a deletion reads the unchanged
    files from the working tree, not one Git process for each file. The budget
    tests use 1,000 entries in one collection, 5,000 files and five editors at
    the same time (@micacms/runtime).
  • No whole media file in memory. An upload streams to disk, the file route
    streams, a revision is a cached, streamed hash, and a URL change copies the
    media on disk (@micacms/runtime).
  • A slow network does not block the start, the sync or Publish: a sync
    skips its turn while one runs, a stalled transfer stops, and Git has
    settings for large repositories with many images.
  • mica init writes the starter's model, the same one as
    examples/starter and the getting-started page (@micacms/editor).
  • The release workflow builds without write rights and publishes from a
    separate job; dependencies are audited every week and updated every month.

Fixed

  • Security: the content files refuse a symbolic link out of the content
    root and the .git folder; a route slug is one folder name; a media()
    value stays inside the content root; a name such as constructor is not a
    collection; sign-out removes the unsaved form values that the tab kept
    (@micacms/core, @micacms/runtime, @micacms/editor, @micacms/astro).
  • The first Publish of a new project names git push -u origin HEAD
    when the branch has no upstream (@micacms/runtime).
  • astro add no longer writes a broken configuration: the package has no
    astro-integration keyword (@micacms/astro).
  • A missing value reaches templates empty, never with its default, and
    templates do not get the _key of repeater rows (@micacms/astro).

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 19:42

Ready for others. Rich text edits tables and images, and a toolbar takes a
preset. The editor works with the keyboard and a screen reader on every view,
and CI checks each view with axe. A relation field finds entries as you type,
and entries move by drag, by the keyboard or to a typed position. A new
tags() field holds a free list of words, and @micacms/astro/relations
resolves relations on your pages. Each view of the editor reads only what it
shows. A minimal starter, a general example site, and the documentation on
micacms.com (reference pages, recipes, model changes, a guide for editors)
help a new team to start.

Read Breaking before upgrading from 0.7. mica check and Publish now report a
missing image in rich text. An unknown rich-text toolbar stops the model from
loading.

Breaking

  • Images in rich text are checked. mica check reports an image whose
    file is missing, and Publish refuses it. A missing image with a /path is a
    warning only, because it can be in Astro's public/ folder
    (@micacms/editor, @micacms/runtime).
  • An unknown rich-text toolbar stops the model from loading. toolbar is
    a preset ("minimal", "default", "full") or a list of known features;
    before, an unknown feature was ignored. An older editor ignores a feature
    from a newer model (@micacms/core).
  • Internal: the runtime reads less. ContentFiles has stat(); the media
    list has no dimensions, which /admin/media/info gives for one file; a
    single entry's response has no position (@micacms/runtime).

Added

  • Tables and images in rich text. A table has a header row and one line of
    text in each cell, stored as a Markdown pipe table. An image comes from the
    media library with its alt text, which is required. The toolbar options
    "table" and "image" add the buttons (@micacms/editor-ui,
    @micacms/core).
  • Toolbar presets: toolbar: "minimal" | "default" | "full", or a list of
    features (@micacms/core).
  • Images in rich text on the website. Each entry has its rich-text images
    in _mica.images, made by Astro's image(), and
    renderRichText(text, { images }) writes their address, width and height
    (@micacms/astro).
  • tags(), a field for a free list of short words, with max,
    maxLength, suggestions and default. The editor adds a tag with Enter or
    a comma and offers the suggestions; mica import fills a tags field
    (@micacms/core, @micacms/editor-ui, @micacms/editor).
  • @micacms/astro/relations: related() and relatedAll() resolve
    relation fields with the site's types and warn in astro dev about a
    missing target (@micacms/astro).
  • A searchable relation picker. A relation field finds entries as you
    type, and the chosen entries can be put in a new order (@micacms/editor-ui).
  • Ordering by drag, by the keyboard, or to a position, with one save for
    each move (@micacms/editor-ui).
  • Accessibility. Each page has its own title, a skip link, and the focus on
    its heading after navigation. The menu drawer, the dialogs and the upload
    controls work with the keyboard; read-only fields stay focusable; the
    Publish page labels Before and After. A browser test runs axe on every view
    (@micacms/editor-ui).
  • A "Help for editors" link in the menu opens the guide for editors on
    micacms.com (@micacms/editor-ui).
  • A minimal starter in examples/starter, for
    npm create astro -- --template micacms/mica/examples/starter, with a CI
    workflow that runs mica check and checks the committed model.
  • collectionSlugs, and shared rules for paths in rich text, in
    @micacms/core.

Changed

  • Each view reads what it shows. Opening an entry, the free-URL check, the
    overview, the System page and the change list read only what they show; the
    media file route answers 304 with an ETag; a collection is read eight
    entries at a time (@micacms/runtime, @micacms/core).
  • The editor uses Tiptap 3 (@micacms/editor-ui).
  • Fields stay readable while a form saves. They are read-only, not
    disabled, so the focus stays where it was (@micacms/editor-ui).
  • The example is a general company site, Harbor Lane Consulting in
    examples/company-site, with every field kind, tables and images in rich
    text, and imaginary places.
  • One source of user documentation. The guides are on micacms.com, with
    new reference pages (command line, @micacms/astro, fields, health
    endpoints), recipes, a guide to model changes with tested scripts, a guide
    for an existing site, a guide for editors, the scope with a comparison, a
    pattern for several languages, and an accessibility statement.
  • Contributing: CONTRIBUTING.md, a code of conduct, GOVERNANCE.md,
    issue forms and a pull-request template.

Fixed

  • Saving a form no longer logs a Content-Security-Policy violation
    (@micacms/editor-ui).
  • The media details load the dimensions of the selected file, and the change
    list refreshes after a write and when the window gets the focus, not at each
    navigation (@micacms/editor-ui).

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 14:09

The editor's daily work. Editors choose what to publish, read editing words
instead of Git words, and see on every entry whether it is published. A form
checks its fields while the editor types, keeps unsaved changes when the
session ends, and shows both versions when two editors save the same entry.
When an entry's URL changes, the links to it can follow. Files can be deleted
from the Media view, uploads stay with their entry, and a new content model is
used without a restart.

Read Breaking before upgrading from 0.6. A save no longer checks required
fields; Publish does. Each publication's commit ends with a
Published-with: Mica line. In the local editor, Publish waits while the
branch holds other commits that are not pushed yet.

Breaking

  • Publish takes the chosen changes. The Publish page has a checkbox for
    each change; a change comes with the new entries and files it uses, and the
    rest stays saved. The staging status reports unpushed: { mica, other }
    instead of ahead (@micacms/runtime, @micacms/editor-ui).
  • Required fields are checked at Publish, not at Save. A half-finished
    entry can be saved; the entry page says "Not ready to publish" and names the
    empty fields. A new entry needs a title or a URL (@micacms/runtime).
  • Mica marks its commits. Each publication's commit ends with the trailer
    Published-with: Mica. In the local editor, Publish and its retry refuse
    while the branch holds commits that its upstream does not have and that
    Mica did not make: push them, or move them to another branch
    (@micacms/runtime).
  • Uploads go into the entry's folder. A file uploaded in an entry or
    settings form goes into its own media/ folder; the picker offers that
    folder's files and the shared ones. Files already in the shared folder stay
    there. Videos are refused (@micacms/runtime, @micacms/editor-ui).
  • Slugs and sorting are typed. A collection's own slug field is read from
    the entry's file name and typed as string, never null; a second slug
    field among a collection's own fields stops the build. defaultSort.field
    must be a field of the collection or "position". The coordinates options
    defaultCenter and defaultZoom are removed (@micacms/core,
    @micacms/astro).
  • Validation messages name the field and the limit, such as "Title can have
    at most 120 characters (now 134)." The unused coordinatesSchema export is
    removed (@micacms/core).
  • findReferences also returns settings pages, as
    { kind: "entry" | "singleton", … } (@micacms/runtime).
  • restart_required means only a .gitattributes change. A new content
    model needs no restart (@micacms/self-hosted).

Added

  • Delete in the Media view. A file, or a selection, is deleted when no
    field and no rich text uses it; the view shows where a file is used. The
    delete waits on the Publish page, and Discard brings the file back
    (@micacms/runtime, @micacms/editor-ui).
  • Links follow a URL change. The entry page names the entries and settings
    pages that link to the entry and offers to update their links in the same
    save (@micacms/core, @micacms/runtime, @micacms/editor-ui).
  • Save conflicts show both versions, with "Keep mine" (logged with the
    editor) and "Use theirs" (@micacms/runtime, @micacms/editor-ui).
  • A new content model without a restart. Mica loads it as soon as the
    manifest changes, in both apps; an open page asks the editor to save and
    load it again. A model that cannot be read leaves the old one in use, and
    the System and Publish pages say why (@micacms/runtime,
    @micacms/editor-ui).
  • The end of a session keeps the work. The page offers "Sign in again" and
    returns to the same place; forms keep unsaved changes in the browser tab and
    offer to restore them. A warning comes five minutes before the end. Each
    response names the session's end in x-mica-session-expires
    (@micacms/editor-ui, @micacms/auth-oidc).
  • patternMessage on text fields, and a description for every builder
    option (@micacms/core).
  • relinkReferences and mapMedia in @micacms/core.
  • The log names the editor for Publish, Discard, conflict choices, media
    deletes and "Keep mine" (@micacms/runtime).

Changed

  • Editing words, not Git words. "Say what changed" instead of "commit
    message"; Git details are only on the System page and in a closed "Details
    for developers" section (@micacms/editor-ui).
  • Publish state everywhere. Entries and settings show "Saved · not
    published" with Publish and Discard, lists mark new and changed entries,
    and each change shows when it was saved (@micacms/editor-ui).
  • The form checks fields in the browser when the editor leaves them and
    before a save; each problem links to its field, also from the Publish page
    (@micacms/editor-ui).
  • In astro dev, an unfinished draft is left out with a warning, and the
    rest of the collection loads; a build still fails (@micacms/astro).
  • Dependencies refreshed; the example site uses MapLibre 6 and sharp 0.35.

Fixed

  • "Today" in a date field uses the local date; a half-typed coordinate is
    named as missing instead of 0; the list search no longer matches field
    names; list cells show dates, choices, rich text and files readably; a
    settings page that fails to load no longer shows an empty form
    (@micacms/editor-ui).
  • mica check reads the slug as the file has it (@micacms/editor).