Development, build, and deployment tooling for LinkApps
npm install @linktr.ee/linkappDevelopment, build, and deployment tooling for LinkApps - custom interactive link experiences for Linktree profiles.
``bash`
npm install @linktr.ee/linkapp
Or create a new LinkApp project:
`bash`
npm create @linktr.ee/linkapp@latest
Start the development server with hot reloading and theme preview UI:
`bash`
linkapp dev [--port 3000]
The dev server provides:
- Live preview of all layouts (expanded, featured, carousel)
- Theme switcher with Linktree presets
- Settings editor for testing configurations
- Hot module replacement
Build your LinkApp for production:
`bash`
linkapp build [options]
Options:
- --sourcemap - Generate source maps for debugging--profile
- - Enable bundle profiling--compress
- - Generate Brotli-compressed files (30-40% smaller)
Outputs to dist/ directory with:build-manifest.json
- Content-hashed filenames for cache busting
- with asset versions
- Optimized React vendor chunks for better caching
Deploy your LinkApp to Linktree:
`bash`
linkapp deploy [--qa] [--skip-confirm]
Options:
- --qa - Deploy to QA environment instead of production--skip-confirm
- - Skip confirmation prompt
The deployment process:
1. Validates project structure and configuration
2. Builds if needed (runs linkapp build)linkapp.config.ts
3. Generates manifest files from
4. Packs project into tarball
5. Uploads to Linktree API
6. Returns build ID and admin URL
Authenticate with Linktree using OAuth device flow:
`bash`
linkapp login [--qa] # Login
linkapp logout [--qa] # Logout
Tokens are stored in ~/.config/linkapp/auth-token.json.
Add UI components from the registry:
`bash`
linkapp add
Example: linkapp add button
Test URL matching rules from your config:
`bash`
linkapp test-url-match-rules
Example: linkapp test-url-match-rules https://google.com/search
`json`
{
"bin": {
"linkapp": "bin/cli.js"
}
}
`typescript
import type { AppProps, LinkAppConfig, SettingsElement } from '@linktr.ee/linkapp/types'
// Layout component props
interface MySettings {
title: string
color: string
}
export default function ExpandedLayout({ settings, theme }: AppProps
return {settings.title}
}
`
`typescript
import { useExpandLinkApp } from '@linktr.ee/linkapp/sdk'
// In featured layout, expand to overlay
function FeaturedLayout() {
const expandLinkApp = useExpandLinkApp()
return (
)
}
`
A LinkApp project has this structure:
``
my-linkapp/
├── app/
│ ├── expanded.tsx # Required: default layout
│ ├── featured.tsx # Optional: featured layout
│ ├── featured-carousel.tsx # Optional: carousel variant
│ ├── layout.tsx # Optional: wrapper component
│ ├── globals.css # Global styles
│ └── icon.svg # LinkApp icon
├── components/ # Your components
├── public/ # Static assets (copied to dist/)
├── linkapp.config.ts # Configuration
├── postcss.config.mjs # PostCSS config (Tailwind v4)
├── components.json # Component registry config
└── package.json
The linkapp.config.ts file defines your LinkApp:
`typescript
import { defineConfig } from '@linktr.ee/linkapp/types'
export default defineConfig({
manifest: {
name: 'My LinkApp',
tagline: 'A custom link experience',
category: 'share',
author: {
name: 'Your Name',
website: 'https://example.com'
},
supporting_links: {
terms_of_service: 'https://example.com/terms',
privacy_policy: 'https://example.com/privacy'
}
},
settings: {
title: 'My LinkApp Settings',
elements: []
}
})
`
Important: The manifest.name becomes your LinkApp ID (kebab-cased) and cannot be changed after first deployment.
See the Configuration Reference for all available options.
Uses Rsbuild (Rspack) for fast, optimized builds:
- Entry Point: .linkapp/main.tsx (auto-generated)@/
- Alias: points to project root./
- PostCSS: Supports Tailwind CSS v4
- Asset Prefix: for S3 subdirectory deployment--compress
- Code Splitting: React vendor chunks separated for caching
- Compression: Optional Brotli compression with flag
Compact layout for profile pages:
`typescript
import type { AppProps } from '@linktr.ee/linkapp/types'
interface Settings {
title: string
}
export default function Expanded({ settings, theme, __linkUrl }: AppProps
return (
)
}
`
Hero-style layout for featured content:
`typescript
import { useExpandLinkApp } from '@linktr.ee/linkapp/sdk'
import type { AppProps } from '@linktr.ee/linkapp/types'
export default function Featured({ settings }: AppProps
const expand = useExpandLinkApp()
return (
The featured layout can trigger a modal that displays the expanded layout.
Theme System
LinkApps receive theme data via props:
`typescript
interface Theme {
// Legacy properties (maintained for compatibility)
textColor: string
backgroundColor: string
borderRadius: number // Modern CSS variables (preferred)
cssVariables: Record
}
`Apply CSS variables for theming:
`css
/ app/globals.css /
:root {
--color-primary: var(--theme-primary, #000);
--color-background: var(--theme-background, #fff);
}
`PostMessage API
LinkApps run in iframes and communicate with the parent window:
`typescript
import { useExpandLinkApp } from '@linktr.ee/linkapp/sdk'function MyComponent() {
const expand = useExpandLinkApp()
return (
)
}
`Development
$3
`bash
npm run build # Compile TypeScript
npm run dev # Watch mode
npm run test # Run tests
npm run lint # Lint with Biome
npm run format # Format with Biome
`$3
Link the package globally to test CLI changes:
`bash
cd packages/linkapp
npm run build
npm linkcd ../../apps/my-test-app
linkapp dev
`$3
-
build - Compile TypeScript to dist/
- dev - Watch mode compilation
- test - Run Vitest tests
- test:watch - Watch mode for tests
- lint - Lint with Biome
- format - Format with Biome
- clean - Remove build artifactsKey Concepts
$3
The LinkApp ID is derived from
manifest.name using kebab-case:
- "My Cool App" → "my-cool-app"
- This ID is permanent and identifies your LinkApp across deployments
- Cannot be changed after first deployment$3
The
supports_featured_layout setting is auto-detected based on the presence of app/featured.tsx. You don't need to manually configure it.$3
Settings are defined as an array of elements:
`typescript
elements: [
{
type: 'text',
id: 'title',
label: 'Title',
defaultValue: 'Hello'
},
{
type: 'select',
id: 'style',
label: 'Style',
options: ['minimal', 'bold'],
defaultValue: 'minimal'
},
{
type: 'array',
id: 'items',
label: 'Items',
element: {
type: 'text',
id: 'name',
label: 'Name'
}
}
]
`Supported types:
text, select, file, switch, array, number, date, colorRequirements
- Node.js >= 18.0.0
- npm >= 10.0.0
Related Packages
-
@linktr.ee/create-linkapp - Scaffolding tool for new projects
- @linktr.ee/registry` - Component registrySee LICENSE file in repository root.