Using the Soonex i18n template
2026-05-08
Clone corex-ui repos, run Mix and Tableau, tune i18n and themes, plus a Markdown gallery (tables, alerts, footnotes, images) matching MDEx in config.
This guide walks through cloning soonex_i18n, running the static site pipeline, renaming the OTP app, and tuning locales, themes, color mode, and demo chrome. Further down, a Markdown feature gallery shows what MDEx emits for the extensions enabled in config/config.exs (table, tasklist, strikethrough, autolink, alerts, footnotes, and syntax_highlight: nil plus the SoonexI18n code pipeline).
Get the code
The localized Tableau site lives in its own repository under the corex-ui organization.
Clone over HTTPS
git clone https://github.com/corex-ui/soonex_i18n.git cd soonex_i18n Clone over SSH
If you prefer SSH:
git clone git@github.com:corex-ui/soonex_i18n.git
Then cd into the repo directory you cloned.
Single-language template
For a single-language layout without locale path prefixes, use the sibling template soonex:
git clone https://github.com/corex-ui/soonex.git Work inside the Corex monorepo
If you develop from the monorepo checkout, use templates/soonex_i18n. The default is {:corex, "~> 0.1.0-beta.5"} from Hex; to build against a sibling corex repo, switch mix.exs to {:corex, path: "../../corex"} and run mix deps.get so deps/corex matches that checkout (the corex/hooks and corex/select style imports in assets/js/site.js stay the same).
First run
From the repository root, in order:
mix deps.getmix setup
Or runmix localize.download_locales(and any other steps your checkout documents) if you are not using the defaultsetupalias.cd assets && npm install && cd ..mix assets.build- Either
mix tableau.buildfor a production tree under_site/, ormix tableau.serverfor the dev server with reload.
Rename the project
From the repo root, choose a snake_case OTP application name (lowercase letters, digits, underscores only). Commit or branch first, the rename task does not provide an undo.
mix project.rename acme What the rename task updates
lib/,config/,test/,priv/, andmix.exs- Selected
package.json/package-lock.jsonentries where applicable - Directory renames such as
lib/soonex_i18n/→lib/acme/andlib/soonex_i18n_web/→lib/acme_web/, plus matchingtest/trees when present
After it finishes, run mix format and mix compile.
What you still edit by hand
Markdown under _posts/ and the root README are intentionally not rewritten so clone URLs like corex-ui/soonex_i18n stay accurate. Update branding copy yourself if you rebrand the app.
Locales and static posts
Gettext and Localize
- Open
lib/soonex_i18n/gettext.exand setdefault_localeandallowed_localesto the languages you ship. - Align
config/config.exs:localizewith those locale codes:supported_localesand an explicitdefault_localestring (for example"en"). The explicit default keepsmix tableau.buildand CI from depending on POSIXLANG(oftenC.UTF-8on GitHub Actions), which is not a valid BCP 47 tag for Localize’s default-locale resolution.
Permalinks and _posts/
Add or remove Markdown under _posts/ with one permalink per language (for example /en/docs/ and /ar/docs/). Tableau emits one static tree per permalink.
Themes
Allowed theme ids and the default live in lib/soonex_i18n/theme.ex.
Import the matching priv/design/corex/theme/*.css files in assets/css/site.css so every [data-theme="…"] value you expose is present in the CSS graph.
Color mode (light / dark)
Light and dark preference is driven by data-mode on <html>, with helpers in lib/soonex_i18n/mode.ex and client logic under assets/js/mode.js.
Demo panel (Template Options)
The floating Template Options panel lives in lib/layouts/root/demo.ex. You can remove:
- the theme
<.select>block, - the mode
<.toggle_group>block,
or both, and keep the language <.select> if you still want a locale switcher on the static site.
Markdown feature gallery
The snippets below mirror MDEx options under config :tableau, :config, markdown: [mdex: …] and the SoonexI18n post-processing step (SoonexI18n.MDExConverter → SoonexI18n.Markdown.CodeBlocks.transform/1) for fenced and inline code.
Headings
The post layout renders the post title as the page <h1>. In Markdown body text, ## maps to <h2>, ### to <h3>, and so on.
Third-level heading example
Fourth-level heading example
Emphasis, inline code, and strikethrough
Use bold, italic, combined emphasis, backticks for commands and paths, and strikethrough when extensions include strikethrough: true.
Links and autolink
Markdown link: Tableau on Hex. With autolink: true, bare URLs also become links, for example https://hexdocs.pm/mdex/MDEx.html.
Unordered and nested lists
- Clone the template
- HTTPS or SSH
- Optional monorepo path
- Run
mix setup - Build with
mix tableau.buildor serve withmix tableau.server
Ordered lists
- Edit
config/config.exsandlib/soonex_i18n/gettext.exfor locales. - Add posts under
_posts/with a uniquepermalinkper file. - Ship
_site/to your host or CDN.
Task lists
tasklist: true renders GitHub-style checkboxes (inputs are disabled in static HTML):
- Enable MDEx extensions in config
- Replace demo copy with your product story
- Point the waitlist form at your backend
Table
Tables need extension: [table: true]:
| Topic | Where to look |
|---|---|
| Markdown pipeline | lib/soonex_i18n/md_ex_converter.ex, lib/soonex_i18n/markdown/code_blocks.ex |
| MDEx options | config/config.exs → markdown: [mdex: …] |
| Post layout | lib/layouts/post_layout.ex (.typo wraps body HTML) |
Blockquote
Blockquotes use the
.typo blockquotestyles: layer background, border, and italic body text for callouts that are not GitHub alerts.
Image
Site-root paths resolve after mix tableau.build (static files live under _site/):
GitHub-style alerts
With alerts: true, MDEx emits div.markdown-alert blocks. Titles come from the alert keyword.
Note
Use Note for neutral context that readers should notice.
Tip
Use Tip for shortcuts, conventions, or quality-of-life details.
Important
Use Important for security, data loss, or breaking-change warnings.
Warning
Use Warning when behavior may surprise operators.
Caution
Use Caution when the outcome depends on environment or ordering.
Footnotes
Footnotes need footnotes: true. References render as superscript links; definitions are collected at the end of the document1.
Fenced and inline code
Fenced blocks use the SoonexI18n pipeline (Makeup + Corex Code + Clipboard when a language-… class is present):
defmodule Demo do @moduledoc "Shown in the gallery" def hello, do: :soonex end Inline highlighter: Mix.Task.run("tableau.build") and mix deps.get.
Raw HTML (render: [unsafe: true])
With unsafe: true, trusted HTML passes through MDEx. Use sparingly in content you control:
Example: native details / summary
Pair with Ctrl+B style keys using the .typo kbd styles.
Tip: After
mix tableau.build, open_site/en/docs/index.htmlto confirm exactly what shipped for this permalink.
See
SoonexI18n.MDExConverter.convert/4andApplication.get_env(:tableau, :config)[:markdown][:mdex]for the exact option map passed toMDEx.to_html!/2. ↩