Shared packages for Astro/Svelte content-driven websites. This workspace provides design tokens, icons, and base UI components that can be consumed by multiple websites with minimal coupling.
The monorepo is a "pattern library" approach, NOT a "shared dependency" approach:
sites should have zero @knots/* dependencies, not even as dev dependencies.
The @knots/* packages are essentially a "pattern cookbook" that you copy from, not import from.
Maintain various documentation and a design system and component library for both each site and also at the parent monorepo.
Refactor to streamline the process of developing and updating patterns and components, functions, etc across multiple sites.
We are trying to maintain these as elegant design systems, in addition to robust, state-of-the-art websites.
Hypernova (sites/hypernova-site)
LogoGrid--LogoOnly.astro accepting portfolio data; Class5 and Kearny Jackson logos fixed./trademarks/trademark__Hypernova--Dark-Mode.svg and light variant; header background around logo removed.// @ts-check.facts collection.The Water Foundation (sites/twf_site)
public/trademarks and referenced by absolute paths.@knots/*.Quick dev:
pnpm --filter hypernova-site devpnpm --filter twf_site devThis folder is a standalone pnpm workspace. Packages live in packages/* and sites can be included as workspace members for local linking.
pnpm-workspace.yamlpnpm -r buildpnpm --filter <pkg-name> dev@knots/tokens: Design tokens with TypeScript types (colors, scales, future typography/spacings)@knots/icons: Minimal SVG icons as strings with a getIcon(name) helper@knots/astro: Base Astro components (e.g., Button.astro) and re-exports@knots/svelte: Base Svelte components (e.g., Button.svelte) and re-exports@knots/brand-config: Brand configuration objects (e.g., water brand)Astro component pattern:
# Copy the pattern file into your site
cp packages/astro/src/components/Button.astro sites/my-site/src/components/
Then use in your site:
---
import Button from "../components/Button.astro";
---
<Button label="Click me" />
Svelte component pattern:
# Copy the pattern file
cp packages/svelte/src/components/Button.svelte sites/my-site/src/components/
Then use:
<script>
import Button from "../components/Button.svelte";
</script>
<Button label="Click me" />
Design tokens pattern:
# Copy token structure into your site
cp packages/tokens/src/index.ts sites/my-site/src/config/tokens.ts
# Edit to match your brand
Then use in Astro with CSS variables:
---
import tokens from "../config/tokens";
const primary = tokens.colors.primary[500];
---
<style define:vars={{ primary }}>
.cta { background: var(--primary); }
</style>
Icons pattern:
# Copy icon helper into your site
cp packages/icons/src/index.ts sites/my-site/src/utils/icons.ts
Use as inline SVG:
import getIcon from "../utils/icons";
const arrowSvg = getIcon("arrowRight");
Brand config pattern:
# Copy brand config structure
cp packages/brand-config/src/index.ts sites/my-site/src/config/brand.ts
# Adapt to your brand
Use in your site:
import { myBrand } from "../config/brand";
console.log(myBrand.colors.primary);
Sites are git submodules that develop independently. They're included in the workspace for development convenience, but they copy patterns rather than depending on packages.
# 1. Create site repo separately (GitHub/etc)
# 2. Add as submodule to astro-knots
git submodule add https://github.com/org/new-site.git sites/new_site
# 3. Add to workspace (for convenience)
# Edit pnpm-workspace.yaml, add: - sites/new_site
# 4. Initialize and install
git submodule update --init sites/new_site
pnpm install
# 5. Copy patterns as needed
cd sites/new_site
cp ../../packages/astro/src/components/Button.astro src/components/
# Adapt to your site's brand
Sites work independently:
cd sites/cilantro-site
pnpm install # Site has its own dependencies
pnpm dev # Site runs standalone
pnpm build # Site builds standalone
# Deploy: Vercel watches the site's own repo
# No dependency on astro-knots for deployment
When a site needs a pattern from the library:
# 1. Find the pattern you need
ls packages/astro/src/components/
# 2. Copy into your site
cp packages/astro/src/components/Button.astro sites/my-site/src/components/
# 3. Adapt to your site's brand and needs
# Edit the copied file to match your design
# 4. Commit in your site's repo
cd sites/my-site
git add src/components/Button.astro
git commit -m "Add button component (from knots pattern)"
We may eventually publish @knots/* to npm, allowing sites to optionally use standard npm dependencies instead of copying. For now, copy/paste keeps sites independent and works for our scale.
Current approach (copy/paste):
Future with published packages:
@knots/astro would have peerDependencies on astro; @knots/svelte on sveltepnpm -r buildpnpm --filter @knots/tokens buildpnpm --filter @knots/tokens devpnpm --filter cilantro-site devSites are git submodules with independent version control:
# Initialize all submodules
git submodule update --init --recursive
# Update a submodule to latest
git submodule update --remote sites/cilantro-site
# Sync submodule config
git submodule sync
# Work inside a submodule (normal git workflow)
cd sites/cilantro-site
git checkout main
git pull
# ... make changes ...
git add .
git commit -m "Update site"
git push origin main
# Update parent to track submodule change
cd ../..
git add sites/cilantro-site
git commit -m "Update cilantro-site submodule reference"
See CLAUDE.md for comprehensive guidance including: