1import{r as h,w as k}from"./chunk-BV7QT456.BQ71lt_D.js";import{j as e}from"./jsx-runtime.u17CrQMm.js";import{g as r,S as o,R as g,n as j,F as p}from"./jwt-generator.DZpDpWmD.js";import{S as E}from"./seo.DRFtizGJ.js";import{P as N,a as S}from"./PageHero.Li5Wljal.js";import{F as d,b as m,C as I,u as A,c as C,P as T,a as _}from"./FeatureSpecimen.DVDy_4yR.js";import{F as c}from"./SpecimenFrame.D6W5qhJK.js";import{a as l}from"./animate-attributes.CG3A8P5v.js";import{r as P}from"./ArrowRight.es.JKcZaiQP.js";import{C as v}from"./ContentIcon.B25hIPMq.js";import{S as x}from"./SiteLink.DZj8NgI4.js";import{S as R}from"./SlidingHighlight.DL8H39PY.js";import{o as O}from"./Check.es.CGp0En6k.js";import{e as L}from"./Plus.es.Bao4C_up.js";import{C as F}from"./CompareLink.DzsR1fVz.js";import"./interaction.CJtquuJa.js";import"./Copy.es.dliWH5g9.js";import"./IconBase.es.DBo9aoPr.js";import"./ExternalLinks.DYQ1kwe5.js";import"./index.Bq7B3-hS.js";import"./index.CqF9FHED.js";import"./widgets.L_NEDZTt.js";import"./theme.DGKosm2U.js";import"./useCopyFeedback.C3CUKZHR.js";import"./writeClipboard.CzREpoR6.js";/* empty css */import"./DashboardCTA.B38_8cCe.js";import"./signed-in.BONbOMX_.js";import"./session.DC8WxWZ2.js";import"./MatrixGlyph.tcDNoeDL.js";import"./Minus.es.BkAwPtek.js";import"./Stack.es.DwCBOihs.js";import"./Key.es.ClQqBiDz.js";import"./LockKey.es.BTruJ5TD.js";import"./animate.8bTpExtZ.js";import"./ArrowsClockwise.es.D-1KuJhL.js";import"./ClockCounterClockwise.es.D371ziKg.js";import"./Code.es.CmC-fk86.js";import"./Database.es.BYtG2DB6.js";import"./EyeSlash.es.CON-wYJW.js";import"./Lightning.es.Dru4ko2K.js";import"./WebhooksLogo.es.B6ASKa6t.js";import"./Robot.es.OygDB6nE.js";import"./UsersThree.es.DMoiWJSx.js";import"./session-replay.D-oy3Zil.js";import"./comparisons.C8okjm1X.js";const D=[{icon:r.LOCK,slug:"encryption",name:"End-to-end encryption",shortName:"Encryption",tagline:"Secrets are encrypted and decrypted on your machines, the server only ever holds ciphertext.",features:[{name:"Client-side AES-256-GCM encryption",description:"Variable values are encrypted with AES-256-GCM using a key derived from the workspace passphrase via PBKDF2-SHA256 (200,000 iterations) with a workspace-specific salt. Encryption and decryption happen only on client machines."},{name:"Zero-knowledge server storage",description:"The server stores only ciphertext and never sees plaintext values or the workspace passphrase. Decryption requires the locally cached derived key."},{name:"Workspace passphrase management",description:"Set, verify, rotate, and clear workspace encryption passphrases. The CLI verifies a passphrase against sample encrypted variables before caching the derived key, and supports rotating or forgetting keys from the dashboard."},{name:"Encryption SDK",description:"The @goenvless/sdk package exposes encryptValue(), decryptValue(), deriveWorkspaceKey(), importWorkspaceKey(), and passphraseStrength(), and the Python and Ruby SDKs, both envless-sdk, the same helpers in snake_case, so you can encrypt values client-side before writing them through the API."}]},{icon:r.ARROWS_SYNC,slug:"sync",name:"Sync, runtime & environments",shortName:"Sync",tagline:"Get decrypted variables into any process, file, or runtime, without committing .env files.",features:[{name:"Typed runtime import",description:"Import environment variables directly in application code via the typed SDK, with automatic type coercion and no .env files on disk."},{name:"Sync to .env files",description:"envless sync decrypts variables and writes .env.<environment-slug> files with proper bash escaping and a sync timestamp header. Writes are idempotent, unchanged files are skipped to avoid spurious dev-server reloads."},{name:"Process wrapping (envless run)",description:"Inject decrypted variables into a single child process with no disk footprint and no code changes. Forwards SIGINT/SIGTERM to the child and returns its exit code, making it ideal for CI and one-off commands."},{name:"Multi-environment merging",description:"envless run and envless build merge several environments into one process, with later environments winning on a name collision. Sync does not merge: it writes a separate .env.<slug> file per environment."},{name:"Real process.env compatibility",description:"Envless populates the standard process.env alongside the typed env proxy, so libraries that read environment variables directly keep working."},{name:"Project linking (.envless file)",description:"Bind a directory to a workspace, product, project, and one or more environments via interactive or flag-driven CLI. The resulting .envless JSON file is safe to commit and enables non-interactive sync and run."}]}],G=[{icon:r.CODE,slug:"tooling",name:"Developer tooling & type safety",shortName:"Tooling",tagline:"Schema-driven types, compile-time checks, and guardrails that keep secrets out of client bundles.",features:[{name:"Typed variables with auto coercion",description:"Define variable schemas in the dashboard with required/optional flags and defaults. The CLI generates type-safe imports and coerces values to strings, numbers, or booleans at runtime."},{name:"Type declaration generation",description:"envless types generates an envless-env.d.ts declaration file from the dashboard schema, giving IDE autocomplete and compile-time type checking."},{name:"Server vs client variable splitting",description:"Visibility flags separate server-only and client-safe variables, enforced through types, runtime checks, bundler plugins, and ESLint rules to prevent secrets from leaking into client bundles."},{name:"Test overrides",description:"Override env values in tests with __override() and scoped 'using' declarations, without mutating global state."}
1,{name:"Interactive CLI",description:"Guided workspace, project, and environment selection with autocomplete and validation, plus help/version flags, browser-based login, and an optional background npm update check."}]},{icon:r.PLUGS,slug:"integrations",name:"Framework & platform integrations",shortName:"Integrations",tagline:"First-class adapters for the runtimes and deploy targets developers actually use.",features:[{name:"Next.js integration",description:"The withEnvless() build plugin handles client inlining and runtime loading with full support for the App Router, Pages Router, and Edge Runtime."},{name:"Vite plugin",description:"A Vite plugin for SPAs, SvelteKit, Remix-on-Vite, and other Vite-based frameworks with client variable inlining and dev-mode HMR."},{name:"Node.js and Bun support",description:"Side-effect import (/register) or --import flag for Express, Fastify, Hono, and standalone scripts, plus native Bun support via a bunfig.toml preload hook with native crypto and faster cold starts."},{name:"Edge worker support",description:"The withEnvless and Vite plugins inline client-flagged variables into the bundle at build time for Cloudflare, Vercel, and Netlify edge runtimes, and a separate @goenvless/env/edge entry loads them explicitly where a filesystem is not available."},{name:"CI/CD and deploy targets",description:"Works with GitHub Actions, GitLab CI, CircleCI, and generic runners via ENVLESS_TOKEN, plus Vercel, Docker build secrets, Kubernetes (including the ExternalSecret operator), Fly.io, Railway, and Render."}]}],H=[{icon:r.LIGHTNING,slug:"performance",name:"Caching & production performance",shortName:"Performance",tagline:"Fast, resilient access to secrets even under cold starts or network failure.",features:[{name:"On-disk encrypted caching",description:"Ciphertext is cached on disk per workspace and environment exactly as the API returned it, at file mode 0600, and refetched once the 15-minute freshness window lapses. No plaintext value is ever written to the cache."},{name:"Build-time inlining on edge",description:"On edge runtimes the envless build command inlines client-flagged variables at build time, so there is no fetch and no decryption on the request path."},{name:"Cache management",description:"envless cache clear drops the cached ciphertext for the current product, project, and environment, and envless cache clear --all wipes the whole cache directory to force a fresh API fetch."},{name:"Offline fallback",description:"envless whoami falls back to the cached profile with a warning when the API is unreachable, and the in-process runtime serves a fresh on-disk cache without a network call."}]},{icon:r.CLOCK,slug:"versioning",name:"Versioning, history & audit",shortName:"Versioning",tagline:"Every change is snapshotted, attributed, and reversible.",features:[{name:"Variable versioning and history",description:"Publish environment snapshots with version notes and view full change history, including who changed what and when. Add, update, and delete operations are all tracked."},{name:"Version rollback",description:"Roll an environment back to a previous variable snapshot from the API or dashboard."},{name:"Per-variable change history",description:"Track each variable's individual history with event types (created, updated, deleted, restored) and timestamps, with search and s
1orting in the dashboard."},{name:"Workspace activity trail",description:"Every workspace action is recorded with actor information (user ID, name, email), event type, and payload, and is delivered in real time as a signed webhook. Per-variable history is queryable through the API and the dashboard; a workspace-wide query endpoint is not exposed yet."}]},{icon:r.USERS,slug:"collaboration",name:"Collaboration & access control",shortName:"Team",tagline:"Granular roles, scoped keys, and team management across isolated workspaces.",features:[{name:"Role-based access control",description:"Built-in Owner, Admin, and Viewer roles plus custom roles with fine-grained control across 45 granular permissions covering every resource."},{name:"Scoped API keys",description:"Named, rotatable keys (ev_sk_...) with per-resource scopes (workspace, projects, environments, variables, versions, members) at read, write, or none levels. Keys are stored as SHA-256 hashes with usage and last-used tracking."},{name:"Team invitations and member management",description:"Invite members by email with role assignment, resend or revoke pending invites (3-day expiration), update roles, and remove members or self-leave, all tracked via webhooks."},{name:"Multi-tenant workspaces",description:"Create, switch between, and leave isolated workspaces, each with its own settings, icon, plan, projects, and environments."},{name:"Project locking",description:"Lock a project to prevent accidental edits; locked projects show a warning banner and disable edit operations."}]}],K=[{icon:r.WEBHOOK,slug:"api",name:"API, webhooks & authentication",shortName:"API",tagline:"A complete programmatic surface with signed events and flexible sign-in.",features:[{name:"REST API with full CRUD",description:"HTTP API covering workspaces, projects, environments, variables, members, versions, and keys, with encrypted variable values, pagination, and sorting."},{name:"Bulk variable operations",description:"Create or delete many variables in a single call, emitting bulk_created and bulk_deleted events."},{name:"Signed webhooks",description:"Real-time JSON webhooks for 48 workspace event types, signed with HMAC-SHA256 per the Standard Webhooks spec, with at-least-once delivery, 5 exponential-backoff retries, per-endpoint secrets, secret rotation, and delivery history with manual redelivery."},{name:"CLI device-code authentication",description:"Browser-based OAuth device flow for passwordless CLI login. Tokens are cached locally in ~/.envless/config.json (mode 0600) and can be revoked from the dashboard or via envless logout."},{name:"Multi-provider sign-in",description:"Authenticate via email, Google OAuth, GitHub OAuth, or email one-time passwords (OTP) with expiration."},{name:"Optional TOTP second factor",description:"Per-user two-factor authentication with any RFC 6238 authenticator app: SHA1, 6 digits, a 30 second period, and one step of clock drift accepted. Enrolment needs both an app code and an emailed code before it takes effect, and issues 10 single-use recovery codes stored as SHA-256 hashes. It is enforced in the API rather than the dashboard, bound to the sign-in it was verified against, and lasts 30 days or until the next sign-in. Off by default, with no workspace-wide requirement, and it does not apply to CLI tokens or API keys."},{name:"Step-up verification",description:"43 endpoints require a fresh verification before they run, in the dashboard and in the CLI, covering credential changes, access changes, destructive deletes, bulk variable writes, key rotation, and account-level actions. Answer with a six-character emailed code, or an authenticator or recovery code if the second factor is on, and stay elevated for an hour. Not enforced on the public API-key surface."},{name:"Billing and subscriptions",description:"Plan tiers (Free, Dev, Team) with monthly or yearly billing via Polar, customer portal access, invoice history, and plan-based resource limits."}]}],y=[...D,...G,...H,...K],b="Features: Encrypted Secrets Platform",w="Everything Envless does: client-side AES-256 encryption, typed SDK + CLI, framework adapters, encrypted caching, versioning, attributed change history, role-based access control, scoped API keys, and signed webhooks.",u=o+g.features,V="Envless is an end-to-e
1nd encrypted secrets manager that replaces .env files. Values are encrypted with AES-256-GCM on your machine, so the server only stores ciphertext.",M=[{title:"Link your project",description:"Authenticate once with a browser device-code login, then bind the directory to a workspace, product, project, and environment. The resulting .envless file is safe to commit.",command:`envless login 2envless link`,language:"bash"},{title:"Run anything with secrets injected",description:"Wrap any command and Envless injects decrypted variables straight into the process, so no .env file ever touches disk.",command:"envless run -- npm run dev",language:"bash"},{title:"Import typed variables in code",description:"Generate an envless-env.d.ts declaration and read variables through the typed SDK, with IDE autocomplete and compile-time checks. The standard process.env is populated too.",command:`envless types 3 4import { env } from '@goenvless/env/server' 5console.log(env.DATABASE_URL)`,language:"ts"},{title:"Sync to .env when you need it",description:"Need a real file for a tool that expects one? Sync writes idempotent .env.<environment> files so unchanged output never triggers a dev-server reload.",command:"envless sync",language:"bash"}],B={"@type":"BreadcrumbList",itemListElement:[{"@type":"ListItem",position:1,name:"Home",item:o+g.home},{"@type":"ListItem",position:2,name:"Features",item:u}]},W=y.flatMap(t=>t.features.map(n=>n.name)),z={"@type":"WebPage","@id":`${u}/#webpage`,url:u,name:b,description:w,isPartOf:{"@id":`${o}/#website`},about:{"@id":`${o}/#software`},speakable:{"@type":"SpeakableSpecification",cssSelector:[E.DEFINITION]}},U={"@type":"SoftwareApplication","@id":`${o}/#software`,name:"Envless",applicationCategory:"DeveloperApplication",featureList:W},q=()=>e.jsxs("div",{className:"features-deck relative size-full max-lg:[&>*:not(:last-child)]:hidden",children:[e.jsx("div",{className:"features-deck__card absolute inset-x-11 top-0 bottom-0",children:e.jsx(d,{slug:m.BACK,size:c.TILE})}),e.jsx("div",{className:"features-deck__card absolute inset-x-[22px] top-[42px] bottom-0",children:e.jsx(d,{slug:m.MIDDLE,size:c.TILE})}),e.jsx("div",{className:"features-deck__card absolute inset-x-0 top-[84px] bottom-0 max-lg:top-0",children:e.jsx(d,{slug:m.FRONT,size:c.TILE})})]}),$=({page:t,index:n,active:a,onActivate:s})=>e.jsxs(x,{href:j(t.slug),"data-active":a,onPointerEnter:()=>s(n),onFocus:()=>s(n),className:"features-index__row group -mx-3 grid grid-cols-[40px_minmax(0,1fr)_20px] items-center gap-4 md:gap-5 rounded-2xl px-3 py-4 md:py-5 transition-fx hover:bg-foreground
5/[0.03] lg:data-[active=true]:bg-foreground/[0.03] focus-visible:outline-2 focus-visible:outline-primary",children:[e.jsx("span",{className:"grid size-10 place-items-center rounded-[12px] bg-primary-soft text-primary-text",children:e.jsx(v,{name:t.icon,size:20})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("h3",{className:"font-display font-normal text-[24px] md:text-[28px] leading-[1.1] text-foreground transition-fx group-hover:text-primary-text",children:t.name}),e.jsx("p",{className:"mt-1 text-[14px] text-muted-foreground lg:line-clamp-2",children:t.cardDescription})]}),e.jsx(P,{size:16,weight:"bold",color:"currentColor",className:"text-muted-foreground transition-fx group-hover:translate-x-[3px] group-hover:text-primary-text"})]}),Y=({page:t})=>e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"features-index__stage aspect-[6/5] rounded-[28px] bg-tertiary p-4 shadow-[0_24px_60px_-28px_var(--shade-deep)]",children:e.jsx("div",{className:"features-index__pane size-full",children:e.jsx(d,{slug:t.slug,size:c.HERO})},t.slug)}),e.jsx("p",{className:"mt-4 text-[14px] text-muted-foreground",children:t.eyebrow})]}),J=()=>{const[t,n]=h.useState(null),a=p[t??0]??p[0];return e.jsx("section",{className:"features-index pb-20 md:pb-28",children:e.jsxs("div",{className:"max-w-section mx-auto px-5 md:px-[60px]",children:[e.jsx("h2",{...l(),className:"font-display font-normal text-foreground text-[32px] md:text-[48px] leading-[1.05] mb-8 md:mb-12",children:"Explore in depth"}),e.jsxs("div",{className:"grid items-start gap-10 lg:grid-cols-12",children:[e.jsx("ul",{...l(1),className:"features-index__list lg:col-span-7",children:p.map((s,i)=>e.jsx("li",{children:e.jsx($,{page:s,index:i,active:i===t,onActivate:n})},s.slug))}),a&&e.jsx("div",{"aria-hidden":"true","data-md-skip":"",className:"hidden lg:block lg:col-span-5 lg:sticky lg:top-28",children:e.jsx(Y,{page:a})})]})]})})},f='[data-active="true"]',Z=({categories:t,activeSlug:n})=>{const a=h.useRef(null);return h.useEffect(()=>{const s=a.current,i=s==null?void 0:s.querySelector(f);!s||!i||s.scrollWidth<=s.clientWidth||s.scrollTo({left:i.offsetLeft-(s.clientWidth-i.offsetWidth)/2,behavior:window.matchMedia(I).matches?"auto":"smooth"})},[n]),e.jsxs("nav",{ref:a,className:"jump-nav relative flex gap-1 overflow-x-auto rounded-full p-1 [scrollbar-width:none] lg:flex-col lg:overflow-visible lg:rounded-none lg:p-0","aria-label":"Feature categories",children:[e.jsx(R,{active:f,activeKey:n,activeClass:"rounded-full lg:rounded-xl bg-foreground
5/[0.07]"}),t.map(s=>e.jsxs(x,{href:`#${s.slug}`,"data-active":s.slug===n,className:"relative z-10 flex h-9 shrink-0 items-center gap-2.5 whitespace-nowrap rounded-full px-3.5 text-[14px] text-body transition-fx hover:text-foreground data-[active=true]:text-foreground lg:h-10 lg:rounded-xl",children:[e.jsx("span",{className:"inline-flex text-primary-text",children:e.jsx(v,{name:s.icon,size:16})}),s.shortName,e.jsx("span",{className:"ml-auto hidden lg:inline text-[12px] tabular-nums text-muted-foreground",children:s.features.length})]},s.slug))]})},Q=({feature:t})=>e.jsxs("details",{className:"capability-row group",children:[e.jsxs("summary",{className:"flex cursor-pointer list-none items-center gap-3 rounded-lg py-3.5 focus-visible:outline-2 focus-visible:outline-primary [&::-webkit-details-marker]:hidden",children:[e.jsx("span",{className:"feature-check",children:e.jsx(O,{size:12,weight:"bold",color:"currentColor"})}),e.jsx("h3",{className:"flex-1 text-[15px] font-medium leading-snug text-foreground",children:t.name}),e.jsx(L,{size:14,weight:"bold",color:"currentColor",className:"shrink-0 text-muted-foreground transition-fx group-open:rotate-45"})]}),e.jsx("p",{className:"pb-4 pl-[29px] text-[14.5px] leading-relaxed text-body",children:t.description})]}),X=({category:t})=>e.jsxs("section",{id:t.slug,...l(),className:"capability-card scroll-mt-40 lg:scroll-mt-28 rounded-3xl bg-tertiary p-6 md:p-8 shadow-[0_8px_24px_-12px_var(--shade-strong)]",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("span",{className:"category-icon",children:e.jsx(v,{name:t.icon,size:22})}),e.jsx("h2",{className:"font-display font-normal text-[26px] md:text-[32px] leading-[1.1] text-foreground",children:t.name}),e.jsx("span",{"aria-hidden":"true",className:"ml-auto shrink-0 rounded-full bg-foreground
5/[0.05] px-2.5 py-1 text-[12px] tabular-nums text-muted-foreground",children:t.features.length})]}),e.jsx("p",{className:"mt-3 text-[15px] text-muted-foreground",children:t.tagline}),e.jsx("ul",{className:"mt-5 grid md:grid-cols-2 md:gap-x-8",children:t.features.map(n=>e.jsx("li",{className:"capability-item",children:e.jsx(Q,{feature:n})},n.name))})]}),ee=({categories:t})=>{const n=A(t.map(s=>s.slug),C),a=t.reduce((s,i)=>s+i.features.length,0);return e.jsx("section",{className:"py-20 md:py-28 bg-background",children:e.jsxs("div",{className:"max-w-section mx-auto px-5 md:px-[60px]",children:[e.jsx("h2",{...l(),className:"font-display font-normal text-[32px] md:text-[48px] leading-[1.05] text-foreground mb-8 md:mb-12",children:`${a} capabilities`}),e.jsxs("div",{className:"flex flex-col gap-6 lg:grid lg:grid-cols-12 lg:items-start lg:gap-10",children:[e.jsx("div",{className:"sticky top-[72px] z-20 -mx-5 px-5 lg:top-28 lg:mx-0 lg:px-0 lg:col-span-3",children:e.jsx(Z,{categories:t,activeSlug:n})}),e.jsx("div",{className:"flex flex-col gap-5 lg:col-span-9",children:t.map(s=>e.jsx(X,{category:s},s.slug))})]})]})})},te=()=>e.jsx("section",{className:"py-20 md:py-28 bg-background",children:e.jsx("div",{className:"mx-auto max-w-section px-5 md:px-[60px]",children:e.jsxs("div",{...l(),className:"cta-card grid gap-8 rounded-[32px] p-8 md:p-14 lg:grid-cols-[minmax(0,1fr)_auto] lg:items-end",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-display font-normal text-[34px] md:text-[52px] leading-[1.02] text-foreground",children:"See how Envless compares"}),e.jsx("p",{className:"mt-3 text-muted-foreground",children:"Side by side with the tools teams replace."})]}),e.jsx("div",{children:e.jsx(F,{})})]})})}),$e={page:{title:b,description:w,jsonLd:[B,z,U]}},Ye=k(function(){return e.jsxs(e.Fragment,{children:[e.jsx(N,{kind:S.MARKETING,title:"Everything Envless does",subtitle:V,subtitleClassName:"definition",actions:e.jsx(T,{secondaryLabel:"Read the docs",secondaryHref:g.docsGettingStarted}),visual:e.jsx(q,{})}),e.jsx(J,{}),e.jsx(ee,{categories:y}),e.jsx(_,{heading:"From login to running code",steps:M}),e.jsx(te,{})]})});export{Ye as default,$e as handle};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.