diff --git a/src/components/Header.jsx b/src/components/Header.jsx
index b400e89..3a7b031 100644
--- a/src/components/Header.jsx
+++ b/src/components/Header.jsx
@@ -86,7 +86,7 @@ export const Header = forwardRef(function Header({ className }, ref) {
Get Started
diff --git a/src/components/Navigation.jsx b/src/components/Navigation.jsx
index 2466f0f..f23eaed 100644
--- a/src/components/Navigation.jsx
+++ b/src/components/Navigation.jsx
@@ -2,13 +2,11 @@ import { useRef } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import clsx from 'clsx'
-import { AnimatePresence, motion, useIsPresent } from 'framer-motion'
+import { AnimatePresence, motion } from 'framer-motion'
import { Button } from '@/components/Button'
import { useIsInsideMobileNavigation } from '@/components/MobileNavigation'
-import { useSectionStore } from '@/components/SectionProvider'
import { Tag } from '@/components/Tag'
-import { remToPx } from '@/lib/remToPx'
function useInitialValue(value, condition = true) {
let initialValue = useRef(value).current
@@ -20,7 +18,7 @@ function TopLevelNavItem({ href, children }) {
{children}
@@ -28,17 +26,25 @@ function TopLevelNavItem({ href, children }) {
)
}
-function NavLink({ href, tag, active, isAnchorLink = false, children }) {
+function NavLink({ href, tag, active, current, level = 0, children }) {
+ let leftPaddingClass = {
+ 0: 'pl-2',
+ 1: 'pl-3',
+ 2: 'pl-3',
+ }[level] ?? 'pl-10'
+
return (
{children}
@@ -51,57 +57,64 @@ function NavLink({ href, tag, active, isAnchorLink = false, children }) {
)
}
-function VisibleSectionHighlight({ group, pathname }) {
- let [sections, visibleSections] = useInitialValue(
- [
- useSectionStore((s) => s.sections),
- useSectionStore((s) => s.visibleSections),
- ],
- useIsInsideMobileNavigation()
- )
+function isLinkActive(link, pathname) {
+ if (link.href === pathname) {
+ return true
+ }
- let isPresent = useIsPresent()
- let firstVisibleSectionIndex = Math.max(
- 0,
- [{ id: '_top' }, ...sections].findIndex(
- (section) => section.id === visibleSections[0]
- )
- )
- let itemHeight = remToPx(2)
- let height = isPresent
- ? Math.max(1, visibleSections.length) * itemHeight
- : itemHeight
- let top =
- group.links.findIndex((link) => link.href === pathname) * itemHeight +
- firstVisibleSectionIndex * itemHeight
+ return (link.links ?? []).some((childLink) => isLinkActive(childLink, pathname))
+}
- return (
-
+function hasDescendantWithHref(link, href) {
+ return (link.links ?? []).some(
+ (childLink) => childLink.href === href || hasDescendantWithHref(childLink, href)
)
}
-function ActivePageMarker({ group, pathname }) {
- let itemHeight = remToPx(2)
- let offset = remToPx(0.25)
- let activePageIndex = group.links.findIndex((link) => link.href === pathname)
- let top = offset + activePageIndex * itemHeight
+function NavigationLinkItem({ link, pathname, level = 0 }) {
+ let isActive = isLinkActive(link, pathname)
+ // Only one item should be "current" (gets the persistent bg). If a parent and
+ // child share the same href, prefer the deepest child.
+ let isCurrent = link.href === pathname && !hasDescendantWithHref(link, pathname)
return (
-
+
+
+ {link.title}
+
+
+ {isActive && (link.links?.length ?? 0) > 0 && (
+
+ {level === 0 && (
+
+ )}
+ {link.links.map((childLink) => (
+
+ ))}
+
+ )}
+
+
)
}
@@ -110,19 +123,13 @@ function NavigationGroup({ group, className }) {
// state, so that the state does not change during the close animation.
// The state will still update when we re-open (re-render) the navigation.
let isInsideMobileNavigation = useIsInsideMobileNavigation()
- let [router, sections] = useInitialValue(
- [useRouter(), useSectionStore((s) => s.sections)],
- isInsideMobileNavigation
- )
-
- let isActiveGroup =
- group.links.findIndex((link) => link.href === router.pathname) !== -1
+ let router = useInitialValue(useRouter(), isInsideMobileNavigation)
return (
{group.href ? (
{group.title}
@@ -130,56 +137,10 @@ function NavigationGroup({ group, className }) {
{group.title}
)}
-
-
- {isActiveGroup && (
-
- )}
-
-
-
- {isActiveGroup && (
-
- )}
-
-
+
+
{group.links.map((link) => (
-
-
- {link.title}
-
-
- {link.href === router.pathname && sections.length > 0 && (
-
- {sections.map((section) => (
- -
-
- {section.title}
-
-
- ))}
-
- )}
-
-
+
))}
@@ -192,27 +153,30 @@ export const navigation = [
title: 'Documentation',
href: '/docs',
links: [
- { title: 'Install', href: '/docs/install' },
- { title: 'Basics', href: '/docs/quickstart' },
- { title: 'Advanced', href: '/docs/advanced' },
- { title: 'Ops ⛨', href: '/docs/ops' },
- { title: 'GitHub ★', href: 'https://github.com/dotenvx/dotenvx' },
- { title: 'Whitepaper ¶', href: '/dotenvx.pdf' },
+ { title: 'Introduction', href: '/docs/introduction' },
]
},
{
- title: 'Ops ⛨',
- href: '/docs/ops',
+ title: 'Quickstart',
+ href: '/docs/quickstart',
links: [
- { title: 'Install', href: '/docs/ops/install' },
- { title: 'Basics', href: '/docs/ops/quickstart' },
- { title: 'Advanced', href: '/docs/ops/advanced' },
+ {
+ title: 'Node.js',
+ href: '/docs/secrets-in-nodejs',
+ links: [
+ { title: 'Introduction', href: '/docs/secrets-in-nodejs' },
+ { title: 'Express', href: '/docs/secrets-in-express' },
+ ],
+ },
]
},
{
title: 'Guides',
href: '/docs/guides',
links: [
+ { title: 'Install', href: '/docs/install' },
+ { title: 'Basics', href: '/docs/quickstart' },
+ { title: 'Advanced', href: '/docs/advanced' },
{ title: 'Quickstart: Run', href: '/docs/quickstart/run' },
{ title: 'Quickstart: Environments', href: '/docs/quickstart/environments' },
{ title: 'Quickstart: Encrypt', href: '/docs/quickstart/encryption' },
@@ -249,6 +213,16 @@ export const navigation = [
{ title: 'llms.txt', href: '/llms.txt' },
]
},
+ {
+ title: 'Ops ⛨',
+ href: '/docs/ops',
+ links: [
+ { title: 'Install', href: '/docs/ops/install' },
+ { title: 'Basics', href: '/docs/ops/quickstart' },
+ { title: 'Advanced', href: '/docs/ops/advanced' },
+ ]
+ },
+
]
export function Navigation(props) {
diff --git a/src/pages/docs/cli/index.mdx b/src/pages/docs/cli/index.mdx
new file mode 100644
index 0000000..acb3cc9
--- /dev/null
+++ b/src/pages/docs/cli/index.mdx
@@ -0,0 +1,7 @@
+import { HeadRedirect } from '@/components/HeadRedirect'
+
+
+
+# Redirecting
+
+Click here if you are not redirected.
diff --git a/src/pages/docs/cli/introduction.mdx b/src/pages/docs/cli/introduction.mdx
new file mode 100644
index 0000000..b04bcd1
--- /dev/null
+++ b/src/pages/docs/cli/introduction.mdx
@@ -0,0 +1,7 @@
+export const description =
+ 'Introduction'
+
+##### [CLI Reference](/docs)
+# Introduction
+
+TODO
diff --git a/src/pages/docs/introduction.mdx b/src/pages/docs/introduction.mdx
new file mode 100644
index 0000000..58018b6
--- /dev/null
+++ b/src/pages/docs/introduction.mdx
@@ -0,0 +1,13 @@
+export const description = 'Introduction'
+
+##### [Documentation](/docs)
+# Introduction
+
+Dotenvx is the secrets CLI for developers.
+
+## Quickstart
+
+Learn how to get Dotenvx set up in your project.
+
+* [Node.js Quickstart](/docs/secrets-for-nodejs)
+* [Express Quickstart](/docs/secrets-for-express)
diff --git a/src/pages/docs/quickstart/index.mdx b/src/pages/docs/quickstart/index.mdx
index ebadc3c..113e4fe 100644
--- a/src/pages/docs/quickstart/index.mdx
+++ b/src/pages/docs/quickstart/index.mdx
@@ -15,7 +15,7 @@ export const description =
'Manage secrets with dotenvx'
##### [Documentation](/docs)
-# Basics
+# Quickstart
Learn the basics of `dotenvx` in just a few minutes. {{ className: 'lead' }}
@@ -23,21 +23,6 @@ Learn the basics of `dotenvx` in just a few minutes. {{ className: 'lead' }}
- multiple environments
- encrypted envs
-## Quickstart
-
-> Install and use it in code just like `dotenv`.
-
-```sh
-npm install @dotenvx/dotenvx --save
-```
-```js
-// index.js
-require('@dotenvx/dotenvx').config()
-// or import '@dotenvx/dotenvx/config' // for esm
-
-console.log(`Hello ${process.env.HELLO}`)
-```
-
## Run Anywhere
> Run it with `dotenvx run -- yourcommand`.
diff --git a/src/pages/docs/secrets-in-express.mdx b/src/pages/docs/secrets-in-express.mdx
new file mode 100644
index 0000000..5a07b9a
--- /dev/null
+++ b/src/pages/docs/secrets-in-express.mdx
@@ -0,0 +1,51 @@
+import InstallNodeSdkCodeGroup from '@/pages/partials/installNodeSdkCodeGroup.mdx'
+
+##### [Documentation](/docs)
+# Encrypt secrets in Express
+
+Learn how to encrypt your first .env file using Express and the Dotenvx Node.js SDK.
+
+## Prerequisites
+
+To get the most out of this guide, you'll need to:
+
+* [Install dotenvx](/docs/install)
+* [Create your account](https://dotenvx.com/signup) (optional)
+
+## 1. Install
+
+Get the Dotenvx Node.js SDK.
+
+
+
+## 2. Encrypt env file
+
+Encrypt your .env file.
+
+```sh {{ title: '$ terminal' }}
+npx dotenvx encrypt
+```
+
+## 3. Inject secrets
+
+Then inject your encrypted secrets at runtime.
+
+
+```js {{ title: 'index.js' }}
+require('@dotenvx/dotenvx').config()
+const express = require('express')
+
+const app = express()
+app.use(express.json())
+
+app.get('/', (req, res) => {
+ res.json({
+ ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY
+ })
+})
+
+const port = process.env.PORT || 3000
+app.listen(port, () => {
+ console.log(`Server running on http://localhost:${port}`)
+})
+```
diff --git a/src/pages/docs/secrets-in-nodejs.mdx b/src/pages/docs/secrets-in-nodejs.mdx
new file mode 100644
index 0000000..57efb3f
--- /dev/null
+++ b/src/pages/docs/secrets-in-nodejs.mdx
@@ -0,0 +1,38 @@
+import InstallNodeSdkCodeGroup from '@/pages/partials/installNodeSdkCodeGroup.mdx'
+
+##### [Documentation](/docs)
+# Encrypt secrets in Node.js
+
+Learn how to encrypt your first .env file using the Dotenvx Node.js SDK.
+
+## Prerequisites
+
+To get the most out of this guide, you'll need to:
+
+* [Install dotenvx](/docs/install)
+* [Create your account](https://dotenvx.com/signup) (optional)
+
+## 1. Install
+
+Get the Dotenvx Node.js SDK.
+
+
+
+## 2. Encrypt
+
+Encrypt your .env file.
+
+```sh {{ title: '$ terminal' }}
+npx dotenvx encrypt
+```
+
+## 3. Inject
+
+Then inject your encrypted secrets at runtime.
+
+
+```js {{ title: 'index.js' }}
+require('@dotenvx/dotenvx').config()
+
+console.log(`ANTHROPIC_API_KEY: ${process.env.ANTHROPIC_API_KEY}`)
+```
diff --git a/src/pages/partials/installNodeSdkCodeGroup.mdx b/src/pages/partials/installNodeSdkCodeGroup.mdx
new file mode 100644
index 0000000..e1c78e0
--- /dev/null
+++ b/src/pages/partials/installNodeSdkCodeGroup.mdx
@@ -0,0 +1,19 @@
+
+
+```bash {{ title: "npm" }}
+npm install @dotenvx/dotenvx
+```
+
+```bash {{ title: "yarn" }}
+yarn add @dotenvx/dotenvx
+```
+
+```bash {{ title: "pnpm" }}
+pnpm add @dotenvx/dotenvx
+```
+
+```bash {{ title: "bun" }}
+bun add @dotenvx/dotenvx
+```
+
+
diff --git a/src/styles/tailwind.css b/src/styles/tailwind.css
index 4425af7..5752946 100644
--- a/src/styles/tailwind.css
+++ b/src/styles/tailwind.css
@@ -19,3 +19,14 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
+
+@layer components {
+ .prose h5 a {
+ color: var(--tw-prose-captions);
+ text-decoration: none;
+ }
+
+ .prose h5 a:hover {
+ color: var(--tw-prose-body);
+ }
+}
diff --git a/typography.js b/typography.js
index c58a687..515ef0d 100644
--- a/typography.js
+++ b/typography.js
@@ -3,9 +3,9 @@ module.exports = ({ theme }) => ({
css: {
'--tw-prose-body': theme('colors.zinc.700'),
'--tw-prose-headings': theme('colors.zinc.900'),
- '--tw-prose-links': theme('colors.yellow.500'),
- '--tw-prose-links-hover': theme('colors.yellow.600'),
- '--tw-prose-links-underline': theme('colors.yellow.500 / 0.3'),
+ '--tw-prose-links': '#000000',
+ '--tw-prose-links-hover': '#000000',
+ '--tw-prose-links-underline': 'rgb(9 9 11 / 0.55)',
'--tw-prose-bold': theme('colors.zinc.900'),
'--tw-prose-counters': theme('colors.zinc.500'),
'--tw-prose-bullets': theme('colors.zinc.300'),
@@ -21,9 +21,9 @@ module.exports = ({ theme }) => ({
'--tw-prose-invert-body': theme('colors.zinc.400'),
'--tw-prose-invert-headings': theme('colors.white'),
- '--tw-prose-invert-links': theme('colors.yellow.400'),
- '--tw-prose-invert-links-hover': theme('colors.yellow.500'),
- '--tw-prose-invert-links-underline': theme('colors.yellow.500 / 0.3'),
+ '--tw-prose-invert-links': theme('colors.zinc.400'),
+ '--tw-prose-invert-links-hover': theme('colors.zinc.400'),
+ '--tw-prose-invert-links-underline': theme('colors.zinc.400 / 0.5'),
'--tw-prose-invert-bold': theme('colors.white'),
'--tw-prose-invert-counters': theme('colors.zinc.400'),
'--tw-prose-invert-bullets': theme('colors.zinc.600'),
@@ -39,7 +39,7 @@ module.exports = ({ theme }) => ({
// Base
color: 'var(--tw-prose-body)',
- fontSize: theme('fontSize.sm')[0],
+ fontSize: '0.9375rem',
lineHeight: theme('lineHeight.7'),
// Layout
@@ -56,8 +56,8 @@ module.exports = ({ theme }) => ({
// Text
p: {
- marginTop: theme('spacing.6'),
- marginBottom: theme('spacing.6'),
+ marginTop: theme('spacing.4'),
+ marginBottom: theme('spacing.4'),
},
'[class~="lead"]': {
fontSize: theme('fontSize.base')[0],
@@ -67,8 +67,8 @@ module.exports = ({ theme }) => ({
// Lists
ol: {
listStyleType: 'decimal',
- marginTop: theme('spacing.5'),
- marginBottom: theme('spacing.5'),
+ marginTop: theme('spacing.3'),
+ marginBottom: theme('spacing.3'),
paddingLeft: '1.625rem',
},
'ol[type="A"]': {
@@ -100,39 +100,41 @@ module.exports = ({ theme }) => ({
},
ul: {
listStyleType: 'disc',
- marginTop: theme('spacing.5'),
- marginBottom: theme('spacing.5'),
- paddingLeft: '1.625rem',
+ marginTop: theme('spacing.3'),
+ marginBottom: theme('spacing.3'),
+ paddingLeft: '2rem',
},
li: {
- marginTop: theme('spacing.2'),
- marginBottom: theme('spacing.2'),
+ marginTop: theme('spacing.1'),
+ marginBottom: theme('spacing.1'),
},
':is(ol, ul) > li': {
- paddingLeft: theme('spacing[1.5]'),
+ paddingLeft: theme('spacing.2'),
},
'ol > li::marker': {
fontWeight: '400',
color: 'var(--tw-prose-counters)',
},
'ul > li::marker': {
- color: 'var(--tw-prose-bullets)',
+ color: theme('colors.zinc.600'),
+ fontWeight: '700',
+ fontSize: '1.1em',
},
'> ul > li p': {
- marginTop: theme('spacing.3'),
- marginBottom: theme('spacing.3'),
+ marginTop: theme('spacing.1'),
+ marginBottom: theme('spacing.1'),
},
'> ul > li > *:first-child': {
- marginTop: theme('spacing.5'),
+ marginTop: theme('spacing.2'),
},
'> ul > li > *:last-child': {
- marginBottom: theme('spacing.5'),
+ marginBottom: theme('spacing.2'),
},
'> ol > li > *:first-child': {
- marginTop: theme('spacing.5'),
+ marginTop: theme('spacing.2'),
},
'> ol > li > *:last-child': {
- marginBottom: theme('spacing.5'),
+ marginBottom: theme('spacing.2'),
},
'ul ul, ul ol, ol ul, ol ol': {
marginTop: theme('spacing.3'),
@@ -190,7 +192,7 @@ module.exports = ({ theme }) => ({
fontWeight: '600',
fontSize: theme('fontSize.lg')[0],
...theme('fontSize.lg')[1],
- marginTop: theme('spacing.16'),
+ marginTop: theme('spacing.8'),
marginBottom: theme('spacing.2'),
},
h3: {
@@ -201,6 +203,16 @@ module.exports = ({ theme }) => ({
marginTop: theme('spacing.10'),
marginBottom: theme('spacing.2'),
},
+ h5: {
+ color: 'var(--tw-prose-captions)',
+ },
+ 'h5 a': {
+ color: 'var(--tw-prose-captions)',
+ textDecoration: 'none',
+ '&:hover': {
+ color: 'var(--tw-prose-body)',
+ },
+ },
// Media
'img, video, figure': {
@@ -278,16 +290,26 @@ module.exports = ({ theme }) => ({
// Inline elements
a: {
color: 'var(--tw-prose-links)',
- textDecoration: 'underline transparent',
- fontWeight: '500',
- transitionProperty: 'color, text-decoration-color',
- transitionDuration: theme('transitionDuration.DEFAULT'),
- transitionTimingFunction: theme('transitionTimingFunction.DEFAULT'),
+ textDecoration: 'none',
+ borderBottom: '1px solid currentColor',
+ fontWeight: '400',
'&:hover': {
color: 'var(--tw-prose-links-hover)',
- textDecorationColor: 'var(--tw-prose-links-underline)',
+ borderBottomWidth: '2px',
},
},
+ 'a.no-underline': {
+ borderBottom: 'none',
+ },
+ 'a.no-underline:hover': {
+ borderBottom: 'none',
+ },
+ 'h5 a, h5 a:hover': {
+ color: 'var(--tw-prose-captions)',
+ textDecoration: 'none',
+ borderBottom: 'none',
+ fontWeight: '400',
+ },
':is(h1, h2, h3) a': {
fontWeight: 'inherit',
},