## What
Removes the community-maintained **"Other methods"** cloud-providers
page from the self-host docs (it covered Kubernetes/Terraform/Coolify
community deployments).
## Changes
- **Deleted** `developers/self-host/capabilities/cloud-providers.mdx`
and its 13 localized copies (ar, cs, de, es, fr, it, ja, ko, pt, ro, ru,
tr, zh).
- **Removed the slug** from `navigation/base-structure.json` (the source
of truth) and regenerated the derived files via the repo's own
generators (`yarn docs:generate`, `yarn docs:generate-paths`):
- `docs.json` — nav entries dropped for every locale.
- `twenty-shared/.../DocumentationPaths.ts` —
`DEVELOPERS_SELF_HOST_CAPABILITIES_CLOUD_PROVIDERS` constant dropped
(was unused elsewhere).
- **Removed the "Cloud Providers" card** from the `self-host` overview
pages across all locales.
- **Dropped the dangling redirect**
`/developers/self-hosting/cloud-providers` (its destination no longer
exists).
- Cleared the matching entry from the unused `navigation-schema.json`
for consistency.
Net: 68 line deletions across config (pure removal); no insertions.
## Verification
- `grep` confirms **0** remaining references to `cloud-providers`
anywhere in the repo.
- All touched JSON files parse; `oxlint` on twenty-docs reports 0
errors.
- Generators (not hand edits) produced `docs.json` and
`DocumentationPaths.ts`.
> Note: `mintlify broken-links` can't run to completion on this branch
due to a **pre-existing** MDX parse error in the unrelated
`l/ar/.../contribute/contribute.mdx`; the grep above is the equivalent
guarantee that no link points at the removed page.
## Summary
- Documents the new at-rest encryption envelope (`ENCRYPTION_KEY` /
`FALLBACK_ENCRYPTION_KEY`) introduced in v2.5+ and clarifies its
relationship to the legacy `APP_SECRET`-as-encryption-key path.
- Adds a new dedicated **Key rotation** guide covering manual /
Enterprise-cron JWT signing-key rotation, signing-key revocation, and
the online `ENCRYPTION_KEY` rotation procedure (including the new
\`secret-encryption:rotate\` CLI shipped in a follow-up PR).
- Updates the docker-compose quickstart to generate a dedicated
\`ENCRYPTION_KEY\` from day 1.
- Mentions the v2.5+ enc:v2 backfill in the upgrade guide.
English-only — the localized mirrors will be picked up by i18n CI.
## Test plan
- [ ] Mintlify build passes locally / in CI
- [ ] Sidebar entry renders under **Self-Host → Key rotation**
- [ ] Internal links to /developers/self-host/capabilities/key-rotation
resolve from setup.mdx, docker-compose.mdx and upgrade-guide.mdx
---------
Co-authored-by: github-actions <github-actions@twenty.com>
## Summary
- **New Getting Started section** with quickstart guide and restructured
navigation
- **Halftone-style illustrations** for User Guide and Developer
introduction cards using a Canvas 2D filter script
- **Removed hero images** (`image:` frontmatter + `<Frame><img>` blocks)
from all user-guide article pages
- **Cleaned up translations** (13 languages): removed hero images and
updated introduction cards to use halftone style
- **Cleaned up twenty-ui pages**: removed outdated hero images from
component docs
- **Deleted orphaned images**: `table.png`, `kanban.png`
- **Developer page**: fixed duplicate icon, switched to 3-column layout
## Test plan
- [ ] Verify docs site builds without errors
- [ ] Check User Guide introduction page renders halftone card images in
both light and dark mode
- [ ] Check Developer introduction page renders 3-column layout with
distinct icons
- [ ] Confirm article pages no longer show hero images at the top
- [ ] Spot-check a few translated pages to ensure hero images are
removed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions <github-actions@twenty.com>
## Summary
- When `STORAGE_S3_PRESIGNED_URL_BASE` is configured, the file
controller returns a **302 redirect** to a presigned S3 URL instead of
proxying every byte through the server. This eliminates server bandwidth
and CPU overhead for S3-backed deployments.
- For local storage or S3 without a public endpoint, behavior is
unchanged (stream + pipe with security headers).
- Added `getPresignedUrl` to the `StorageDriver` interface (required
method returning `string | null`), with implementations in S3Driver
(uses a separate presign client with the public endpoint), LocalDriver
(returns `null`), and ValidatedStorageDriver (path traversal protection
+ delegation).
- Added a unified `getFileResponseById` method in `FileService` that
performs a single DB lookup and returns either a redirect URL or a
stream, avoiding double lookups.
- Extracted `getContentDisposition` from the header util so both the
proxy path and presigned URL path share the same inline/attachment
allowlist.
- Added MinIO service to `docker-compose.dev.yml` (optional `s3`
profile) for local S3 testing.
- Documented S3 presigned URL setup, CORS, and `nosniff` requirements in
the self-hosting docs.
## Test plan
- [x] All 63 unit tests pass across 5 test suites (util, S3 driver,
validated driver, file storage service, controller)
- [x] `npx nx typecheck twenty-server` passes
- [ ] Manual E2E test with MinIO: `docker compose --profile s3 up -d`,
configure S3 env vars, verify `curl -I` returns 302 with `Location`
header pointing to MinIO
- [ ] Verify local storage (no `STORAGE_S3_PRESIGNED_URL_BASE`) still
streams files with 200 + security headers
- [ ] Verify public assets endpoint still proxies (no redirect)
Made with [Cursor](https://cursor.com)
## Summary
This PR fixes several small documentation issues in the contributor and
setup guides:
- fixes broken docs links in the root README
- corrects multiple typos and capitalization issues in contributor docs
- fixes malformed Markdown for the Redis command in local setup
- improves wording in the Docker Compose self-hosting guide
## Changes
- updated README installation links to the current docs routes
- changed `Open-source` to `open-source`
- fixed `specially` -> `especially` in the frontend style guide
- normalized `MacOS` -> `macOS`, `powershell` -> `PowerShell`, and
`Postgresql` -> `PostgreSQL`
- replaced the invalid `localhost:5432` Markdown link with inline code
- fixed the malformed fenced code block for `brew services start redis`
- cleaned up Redis naming/capitalization and a few grammar issues in the
setup docs
- improved the warning and environment-variable wording in the Docker
Compose guide
## Testing
- not run; docs-only changes
---------
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
## Summary
For security reasons, the code interpreter and logic function drivers
now default based on `NODE_ENV`:
- **Production** (`NODE_ENV=production` or unset): Default to
**Disabled**
- **Development** (`NODE_ENV=development`): Default to **LOCAL** for
convenience
This ensures self-hosted production deployments don't accidentally run
user-provided code without explicit configuration.
## Changes
### Config (`config-variables.ts`)
- `CODE_INTERPRETER_TYPE`: Disabled in prod, LOCAL in dev
- `LOGIC_FUNCTION_TYPE`: Disabled in prod, LOCAL in dev
### Documentation (`setup.mdx`)
- Added **Security Defaults** section explaining NODE_ENV-based behavior
- Fixed variable names: `SERVERLESS_TYPE` → `LOGIC_FUNCTION_TYPE`,
`SERVERLESS_LAMBDA_*` → `LOGIC_FUNCTION_LAMBDA_*`
- Added **Code Interpreter** section with available drivers (Disabled,
Local, E2B)
### Environment files
- `.env.example`: Updated to `LOGIC_FUNCTION_TYPE` with comments
- `.env.test`: Added `LOGIC_FUNCTION_TYPE=LOCAL` for logic function
integration tests
Made with [Cursor](https://cursor.com)
---------
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary
Removes `vite-plugin-checker` and all references to
`VITE_DISABLE_TYPESCRIPT_CHECKER` / `VITE_DISABLE_ESLINT_CHECKER`.
These background checks are no longer needed because our dev experience
now relies on **independent** linters and type-checkers:
- `npx nx lint:diff-with-main twenty-front` for ESLint
- `npx nx typecheck twenty-front` for TypeScript
Running these as separate processes (rather than inside Vite) is faster,
gives cleaner output, and avoids the significant memory overhead that
`vite-plugin-checker` introduces during `vite dev` and `vite build`. The
old env vars to disable them are removed from `vite.config.ts`,
`package.json` scripts, `nx.json`, `.env.example`, and all translated
docs.
## Summary
Completes the migration of the frontend styling system from **Emotion**
(`@emotion/styled`, `@emotion/react`) to **Linaria** (`@linaria/react`,
`@linaria/core`), a zero-runtime CSS-in-JS library where styles are
extracted at build time.
This is the final step of the migration — all ~494 files across
`twenty-front`, `twenty-ui`, `twenty-website`, and `twenty-sdk` are now
fully converted.
## Changes
### Styling Migration (across ~480 component files)
- Replaced all `@emotion/styled` imports with `@linaria/react`
- Converted runtime theme access patterns (`({ theme }) => theme.x.y`)
to build-time `themeCssVariables` CSS custom properties
- Replaced `useTheme()` hook (from Emotion) with
`useContext(ThemeContext)` where runtime theme values are still needed
(e.g., passing colors to non-CSS props like icon components)
- Removed `@emotion/react` `css` helper usages in favor of Linaria
template literals
### Dependency & Configuration Changes
- **Removed**: `@emotion/react`, `@emotion/styled` from root
`package.json`
- **Added**: `@wyw-in-js/babel-preset`, `next-with-linaria` (for
twenty-website SSR support)
- Updated Nx generator defaults from `@emotion/styled` to
`@linaria/react` in `nx.json`
- Simplified `vite.config.ts` (removed Emotion-specific configuration)
- Updated `twenty-website/next.config.js` to use `next-with-linaria` for
SSR Linaria support
### Storybook & Testing
- Removed `ThemeProvider` from Emotion in Storybook previews
(`twenty-front`, `twenty-sdk`)
- Now relies solely on `ThemeContextProvider` for theme injection
### Documentation
- Removed the temporary `docs/emotion-to-linaria-migration-plan.md`
(migration complete)
- Updated `CLAUDE.md` and `README.md` to reflect Linaria as the styling
stack
- Updated frontend style guide docs across all locales
## How it works
Linaria extracts styles at build time via the `@wyw-in-js/vite` plugin.
All expressions in `styled` template literals must be **statically
evaluable** — no runtime theme objects or closures over component state.
- **Static styles** use `themeCssVariables` which map to CSS custom
properties (`var(--theme-color-x)`)
- **Runtime theme access** (for non-CSS use cases like icon `color`
props) uses `useContext(ThemeContext)` instead of Emotion's `useTheme()`
## Summary
Adds comprehensive documentation for the `IS_MULTIWORKSPACE_ENABLED`
configuration variable, which was previously undocumented despite being
a fundamental configuration option that significantly changes how Twenty
behaves.
## Changes
### Self-Host Setup Guide (`setup.mdx`)
Added a new **Multi-Workspace Mode** section that explains:
- **Single-workspace mode (default)**: Only one workspace allowed, first
user gets admin privileges, signups disabled after first workspace
- **Multi-workspace mode**: Multiple workspaces with subdomain-based
URLs (e.g., `sales.your-domain.com`)
- **Related config variables**: `DEFAULT_SUBDOMAIN` and
`IS_WORKSPACE_CREATION_LIMITED_TO_SERVER_ADMINS`
- **DNS configuration**: Wildcard DNS setup for dynamic subdomains
- **Workspace creation restrictions**: How to limit workspace creation
to server admins
### Local Setup Guide (`local-setup.mdx`)
Added an info callout in the environment variables section to make
contributors aware of multi-workspace mode, useful when testing
subdomain-based features.
## Why This Matters
The `IS_MULTIWORKSPACE_ENABLED` variable controls:
- Whether multiple workspaces can exist on a single instance
- URL structure (plain domain vs subdomains)
- First user privileges
- Sign-up behavior after initial setup
- SSO workspace resolution logic
This is critical knowledge for self-hosters who want to run Twenty as a
multi-tenant SaaS.
## Summary
The merge conflict resolution from PR #16705 incorrectly discarded the
new documentation structure changes. This PR updates the navigation JSON
files (the correct approach) to restore the intended changes.
## Changes restored
- New 'Capabilities' and 'How-Tos' subgroups organization
- Renamed sections (e.g., 'Getting Started' → 'Discover Twenty')
- New sections: Data Migration, Calendar & Emails, AI, Views &
Pipelines, Dashboards, Permissions & Access, Billing
- Reorganized Developers section with Extend, Self-Host, and Contribute
groups
## Files updated
- `navigation/base-structure.json`
- `navigation/navigation-schema.json`
- `navigation/navigation.template.json`
## Context
PR #16705 was merged but the merge conflict was incorrectly resolved,
causing all the structural changes to be lost. The previous fix (PR
#16741) updated docs.json directly, but the correct approach is to
update the navigation JSON files instead. This PR properly restores
those changes from the final commit of PR #16705
(`c856e0d598a0056c2bdaf528502e08261daf7c7c`).
---------
Co-authored-by: github-actions <github-actions@twenty.com>
Reorganizing by Feature sections
Capabilities folders to give an overview of each feature
How-Tos folders to give guidance for advanced customizations
Reorganized the Developers section as well, moving the API sub section
there
added some new visuals and videos to illustrate the How-Tos articles
checked the typos, the links and added a section at the end of the
doc.json file to redirect existing links to the new ones (SEO purpose +
continuity of the user experience)
What I have not updated is the "l" folder that, per my understanding,
contains the translation of the User Guide - that I only edited in
English
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> <sup>[Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) is
generating a summary for commit
5301502a32. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@twenty.com>
Co-authored-by: Abdul Rahman <ar5438376@gmail.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>