- README: show the Verso wordmark logo instead of a text title.
- README: original Overleaf copyright now 2014-2026; Verso modifications 2026.
- Instance/version title: 'alpha' -> 'Alpha'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Instance name: stamp the nav title with the build number at deploy time
("Verso V0.<run> alpha") via a sed placeholder fed by GITHUB_RUN_NUMBER,
instead of the static "Verso V1.0 Alpha".
- Title typeface: self-host the EB Garamond latin subset (same one embedded in
the logo SVGs) and apply it to .navbar-title so the instance name matches the
Verso wordmark.
- Sidebar wordmark: let the logo fill the full sidebar column width (drop the
160px cap).
- Project filters: switch the ds-nav active state (filter selection + theme
toggle) from the green tokens to the blue scale, matching the rail.
- Present button: rename the presentation toolbar action from "Preview" to
"Present" / "Présenter" and add a tooltip explaining it publishes the
presentation and opens it in a new tab. New keys present /
present_publishes_and_opens_in_new_tab in en, fr and extracted-translations.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Editor rail: the active item used the Overleaf green accent. Switch
--ide-rail-link-active-color/background to the blue scale (--blue-10/70,
--bg-info-03) to match the Verso palette.
- Footers: remove the default "Fork on GitHub!" right_footer item (redundant
with the "Built on Overleaf" link); right_footer now defaults to [].
- Login: move the hero wordmark into a full-width centered block and bump it to
max-width 480px so it's no longer constrained by the form column.
- Projects dashboard: restore the instance name in the top-left navbar (set
OVERLEAF_NAV_TITLE="Verso V1.0 Alpha") instead of the wordmark logo, and move
the full Verso wordmark to the sidebar's lower section (where the old
"Digital Science" mark sat). Revert HeaderLogoOrTitle to its title-first
behaviour now that the dashboard no longer passes a logo.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Base image: add opencv-python-headless (cv2) and tqdm to the bundled
scientific stack, and python3-venv (needed to build per-project venvs).
Per-project dependencies: a project's requirements.txt is now installed into a
venv cached by its sha256 (python3 -m venv --system-site-packages, so the
bundled stack stays visible and only extra packages are installed); QuartoRunner
points Quarto at it via QUARTO_PYTHON. A per-hash flock serialises concurrent
builds; pip output is merged into output.log; on failure the render falls back
to the base interpreter. Venvs live under PYTHON_VENVS_DIR
(default /var/lib/overleaf/data/python-venvs).
Gating: PythonVenvGate.userCanInstallPython restricts installs to the project
owner + invited collaborators (ignorePublicAccess excludes anonymous/link
users), threaded to CLSI as allowPythonInstall on the editor compile,
presentation export, and publish paths. Behind OVERLEAF_ENABLE_PROJECT_PYTHON_VENV
(enabled in the deployment). Design doc updated; Phase 2 (egress policy) and
Phase 3 (venv eviction) remain.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Deployment: set OVERLEAF_SITE_LANGUAGE=fr so the UI defaults to French.
- fr.json: add French translations for the Verso strings — blank_/example_
{quarto,latex,typst}_project, share_compiled_presentation(_info),
presentation_link_{members,private,public}, reset_link, and preview (which
was missing from fr.json). Other untranslated keys keep falling back to
English via the translations-loader.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The frontend bundles only the locale keys listed in
frontend/extracted-translations.json (a custom webpack translations-loader
filters en.json to that set, normally regenerated by i18next-scanner). Every
key added by hand to en.json without also adding it here renders as its raw
key — which is why "blank_quarto_project", "share_compiled_presentation", etc.
showed up literally in the New-project menu and Share dialog.
Add all introduced keys to extracted-translations.json: blank_/example_
{quarto,latex,typst}_project, share_compiled_presentation(_info),
presentation_link_{members,private,public}, reset_link.
Also enable anonymous read-AND-write share links (edit without an account) via
OVERLEAF_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING; read-only links already worked
through OVERLEAF_ALLOW_PUBLIC_ACCESS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The web service installs a site-wide login gate (router.mjs: webRouter.all('*',
requireGlobalLogin)) whenever Settings.allowPublicAccess is false — which it was,
since OVERLEAF_ALLOW_PUBLIC_ACCESS wasn't set. That gate bounced every anonymous
request to /login, breaking both Overleaf's own link-sharing and the public
presentation links (the dynamic token routes can't be in the exact-match
global whitelist, so there's no per-path exemption — allowPublicAccess is the
intended knob).
Set OVERLEAF_ALLOW_PUBLIC_ACCESS=true on the verso Deployment. Per-project and
per-route authorization still applies, and private presentation links still
require a login (enforced in the serve handler), so only genuinely public
content is reachable anonymously.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two build-speed changes to the Gitea Actions deploy workflow.
(#1) Build the base image only when it changes. The base layers' only
repo input is server-ce/Dockerfile-base, so the prepare step hashes that
file and the base is tagged verso-base:base-<hash>; the app builds FROM
that exact tag. If a base with the current hash already exists in the
registry, the heavy base build (apt ~111s, TeX Live ~51s, Quarto, plus
its ~49s export/push) is skipped entirely — which is every commit that
doesn't touch Dockerfile-base.
(#2) Import/export a registry-backed layer cache (verso-cache:base and
verso-cache:app, mode=max) on both builds. Unchanged layers are reused
instead of rebuilt: yarn install is skipped when package.json is
unchanged, and only the web compile re-runs on a frontend source change.
No new cluster resources — the cache lives as extra tags in the same
in-cluster registry.
First run after this is still a full build (populates the caches and the
hash-tagged base); subsequent commits should be substantially faster.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The cluster nodes' containerd can only pull from registry.alocoq.fr, not
the in-cluster service name. Keep pushing via the in-cluster address (to
bypass the Traefik upload-timeout), but reference registry.alocoq.fr/verso
in the test Deployment and the rolling update. Both addresses front the
same registry storage, so the pushed image resolves at the public name.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The previous approach created a verso-buildkitd-config ConfigMap, but the
workflow's RBAC does not permit creating new cluster resources. Write the
buildkitd.toml (marking the in-cluster registry as http/insecure) directly
inside the buildkit container at runtime via printf, and drop the configMap
volume/mount. No new k8s resources are created.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The TeX Live layer (~3.5 GB) failed to push to registry.alocoq.fr:
Traefik severed the upload mid-stream ("client disconnected during blob
PUT ... unexpected EOF"), buildkit retried at the wrong offset, and the
registry returned "blob upload invalid".
Push to the in-cluster registry Service (registry.git.svc.cluster.local:5000)
instead, so the upload never traverses Traefik. Changes:
- buildctl outputs use registry.insecure=true (registry is plain HTTP)
- add a verso-buildkitd-config ConfigMap with buildkitd.toml marking the
registry http/insecure, so the second build can pull the base image back
- the verso Deployment and rolling update reference the in-cluster image
NOTE: the cluster nodes' containerd must also treat
registry.git.svc.cluster.local:5000 as an insecure registry, otherwise
the kubelet image pull for the test deployment will fail. That is node-
level config outside this repo.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>