Below is a list of some of our favorite and most-used technologies for building web applications for clients.
Why this matters: Controversial, misunderstood, and overhyped though they may be, AI and LLMs are transforming industries and society. Used carefully and responsibly, they are still a valuable tool for innovation and progress. We design and deploy LLM-powered features with a focus on safety, performance, and maintainability, leveraging managed model providers and an SDK-first approach for rapid iteration. Preferred defaults: Vercel AI SDK + AI Gateway for multi-model orchestration; Anthropic and OpenAI as primary model providers.
Provider of the Claude family of models, known for strong reasoning, long context windows, and helpfulness with a focus on safety. Excellent for analytical tasks, documentation-heavy workflows, complex tool use, and structured outputs. We choose Claude when we need high-quality reasoning, longer contexts, and nuanced instruction-following for chat, agents, and knowledge-heavy assistants.
barkup is a config-driven grammar codec that lets humans and LLM agents author the same typed tree as HTML instead of JSON. You declare a grammar of node types and typed attributes and get build, parse, format, and validate with hard guarantees: byte-for-byte id preservation, declared-only attribute coercion, property-tested round-trip identity, and structured errors at the boundary. Since its first release the codec has grown into a full LLM editing toolkit, and every addition was gated on a pre-registered study in our open benchmark series before it shipped: id-anchored patches that address nodes by id and never by position (0.2), focused views that show the model only the part of the tree an edit concerns (0.3), content search that grounds a plain-language request to exact target nodes (0.4), and selectNodes, a deterministic structural selector that hands fan-out edits to code instead of the model (0.5). We built barkup at Lightning Jar and extracted it from Replicator, our AI document platform, where it powers the way an assistant reads and writes template layouts. It has zero runtime dependencies and is published on npm as @kevinpeckham/barkup under the MIT license. We reach for it whenever a model needs to author or edit structured data reliably, because HTML is a format the model has deep pre-trained fluency in.
Related reading: Stable IDs Are All You Need: Seven Studies on Letting LLMs Edit Trees
State-of-the-art language and multimodal models used for chat, content generation, extraction, and code-focused tasks. Broad ecosystem support, tools/function calling, and strong multimodal capabilities make it a versatile default. We reach for OpenAI when we need wide capability coverage, robust tooling, and predictable performance across chat, embeddings, and function/tool workflows.
Visit OpenAI (ChatGPT / GPT models) →
A managed gateway that unifies access to multiple model providers with a single endpoint, centralizing API keys, rate limiting, caching, and observability. It provides request analytics, cost controls, retry/backoff strategies, and prompt/version governance. We adopt Gateway to de-risk vendor lock-in, improve reliability at scale, and gain visibility into latency, token usage, and cost across providers and environments. Licensing notes: SaaS gateway; models remain provider-side. We can route traffic to alternative gateways or direct APIs to avoid lock-in.
A TypeScript-first toolkit for building AI features into web apps with streaming UI, multi-provider support, and server/client utilities. It simplifies chat, tool-calling, RAG, and function invocation with first-class React/Svelte adapters and edge-friendly primitives. We use it to prototype quickly, support multiple model vendors without rewriting app logic, and ship reliable, streaming conversational UIs with minimal boilerplate.
Why this matters: Clear, type-safe APIs prevent integration drift, reduce incidents, and make feature delivery predictable. We design APIs for clarity, performance, and safety—favoring type-safe schemas, real-time capabilities, and standards-based integrations. Preferred defaults: GraphQL for complex domains, tRPC for TS monorepos, Webhooks for eventing, Zod/Valibot for schemas.
Our preferred choice for complex domains, enabling strongly-typed schemas, precise data fetching, and powerful tooling like code generation and caching. We implement schema governance, persisted queries, and performance-aware resolvers to keep APIs fast and predictable.
A tiny, fast library for generating cryptographically strong, URL-friendly unique IDs with customizable alphabets and lengths. We use NanoID for public-facing identifiers, idempotency keys, and correlation IDs where short, non-sequential, collision-resistant tokens improve UX and security compared to UUID v4.
A great fit for full-stack TypeScript apps where end-to-end type safety and developer velocity are paramount. We choose tRPC when teams benefit from shared types without the overhead of an additional query language.
A lean, fast schema library for parsing and validation with strong TypeScript inference. We use Valibot to validate inputs at the edge and server boundaries, ensuring trustworthy data pipelines.
We integrate and expose webhooks to connect systems and automate workflows across services. We focus on signature verification, retries with exponential backoff, idempotency keys, and audit logging for reliability.
We make extensive use of WebSockets for low-latency, bidirectional communication—ideal for collaborative UIs, live dashboards, and streaming interactions. Our implementations emphasize backpressure, reconnection strategies, and secure auth handshakes.
A popular, ergonomic schema validator with excellent DX and ecosystem integrations. We use Zod where broad community support and familiar patterns speed up delivery.
Why this matters: Security is trust—modern auth and session practices protect users and keep compliance teams comfortable. Security is foundational. We standardize on modern auth, strong session management, and defense-in-depth controls to protect users and systems. Preferred defaults: BetterAuth for app auth, token-based sessions with rotation, 2FA (TOTP + WebAuthn), Arcjet for edge protection.
We use Arcjet to enhance security at the application edge—protecting against bots, abuse, credential stuffing, and anomalous traffic. Arcjet pairs well with serverless/edge stacks, adding risk-based controls and observability to critical endpoints.
Our preferred authentication solution for modern web apps—clean APIs, strong multi-tenant support, and integration-friendly flows. We insist on two-factor authentication (2FA) for client logins and design enrollment/recovery flows that balance security with usability.
A fast, well-audited library to sanitize HTML and SVG against XSS attacks in browsers and Node.js. We run DOMPurify at render time or on ingestion to neutralize scripts, event handlers, and dangerous URLs—paired with strict CSP and escaping for defense-in-depth.
Environment variables and secrets are a traditional organizational security weak point—API keys and credentials end up committed in plaintext .env files, pasted into chat, and copied between machines. We use 1Password as the secure vault for those secrets, with access governed per-vault and per-team rather than by passing raw values around. 1Password integrates directly with Varlock through the @varlock/1password-plugin: secrets are declared in .env.schema as op:// references and resolved at load time—pulled from a 1Password vault using a service account in CI/CD and production, or desktop-app biometric auth in local development—so plaintext secrets never live in the repository or on developer machines.
We use Renovate (by Mend) to keep dependencies current—opening pull requests as new versions ship across npm, GitHub Actions, Docker images, and more, with release notes inlined so reviewers see what changed. Renovate's config supports grouping related updates, scheduling noisy ecosystems to off-hours, pinning or ranging strategies per package, and auto-merging trusted updates that pass CI, which keeps the dependency graph healthy without drowning the team in PRs.
We use Snyk to find and fix known vulnerabilities across the stack—open-source dependencies (SCA), first-party code (SAST), containers, and infrastructure as code—mapped against its curated vulnerability database. Snyk integrates with the repository and CI/CD, opening automated fix pull requests and enforcing license and security policy gates without slowing delivery.
We use Socket.dev to defend the software supply chain—proactively detecting malicious or risky open-source packages: typosquats, install-script abuse, obfuscated code, and hijacked maintainer releases, often before a CVE is ever published. Socket.dev integrates into pull requests and CI, flagging dangerous dependency changes at review time so threats are caught before they reach production rather than after.
We favor token-based auth (short-lived access tokens with refresh rotation) for stateless scaling across serverless and edge environments. Our implementations emphasize secure storage, rotation, and scoping with least-privilege principles.
Visit Token-based Authentication →
2FA is a requirement for client logins. We support TOTP apps, WebAuthn/passkeys, and backup codes for resilience. We design secure enrollment, device management, and recovery to minimize lockouts while maintaining strong posture.
Visit Two-Factor Authentication (2FA) →
We use Varlock to manage environment variables from a single committed schema (.env.schema) with decorators for required, typed, and sensitive values—replacing framework-native env access with one consistent, validated source of truth. Varlock validates configuration at build and runtime, generates TypeScript types, and keeps secrets explicitly marked and out of logs—giving us uniform, safe config handling across projects regardless of host or framework. For sensitive values it integrates with 1Password through the @varlock/1password-plugin, resolving op:// secret references at load time so credentials stay in a vault rather than in plaintext .env files.
Why this matters: Choosing the right runtime and hosting improves reliability, security, and developer velocity from day one. We choose runtimes and hosting that balance security, developer experience, and performance. Our defaults favor fast iteration locally and reliability in production, with growing adoption of secure-by-default platforms. Preferred defaults: Bun for local dev, Node.js for production, Vercel for hosting and edge.
Our preferred development runtime for its fast install, test, and dev server performance. Bun streamlines local DX with speedy tooling and modern APIs. We use Bun to accelerate feedback loops during development while keeping parity with production targets.
An increasingly important part of our stack due to secure-by-default permissions, native TypeScript support, and web-standard APIs. We consider Deno for apps where sandboxing, permission scoping, and edge deployment are priorities.
Standard container tooling for packaging apps and dependencies into immutable images, ensuring consistent behavior across dev, CI, and production. We use Docker for local service orchestration (Compose), hermetic builds, and CI pipelines; images can be deployed to managed platforms or orchestrators when serverless isn’t a fit.
Our preferred production runtime thanks to its maturity, ecosystem depth, and predictable operational model across serverless and containerized workloads. We optimize Node for cold starts, streaming responses, and observability in modern hosting environments.
We frequently host on Vercel for its excellent developer experience, preview environments, instant rollbacks, built-in firewall capabilities, and Edge Runtime. Vercel’s serverless and edge primitives pair well with our frameworks (SvelteKit, Vue/Nuxt, Astro) for globally fast delivery.
Why this matters: Centralizing content and product data shortens time-to-publish, lowers error rates, and keeps every channel consistent. Platforms that centralize product data, digital assets, and content, enabling omnichannel delivery, governance, and a single source of truth across websites, apps, and commerce. Preferred defaults: Pimcore for data-heavy catalogs; Sanity for bespoke editorial workflows; Hygraph for GraphQL-first federation.
barkdown is a Markdown to DOM round-trip codec, guaranteed to invert marked. Parse markdown to HTML, edit it as a live DOM (contenteditable, WYSIWYG, or programmatic transforms), and serialize back to markdown that is provably the same document. The contract is a testable mathematical property: one round trip canonicalizes any input, a second is byte-identical, footnotes survive exactly, and unknown elements pass through as raw HTML with no silent loss. It is the sibling of barkup: barkup guards the tree's identity, barkdown guards the prose's. We extracted it from our production blog CMS, where every keystroke of the WYSIWYG editor round-trips through it, and the guarantees are enforced by a corpus suite plus property tests running about 2,000 random documents per run. Published on npm as @kevinpeckham/barkdown under the MIT license.
Related reading: The Untested Half of Your WYSIWYG
A GraphQL-native, headless content platform designed for federating content across sources and delivering it to any frontend. Hygraph excels at structured content modeling, schema stitching via Remote Sources, and performant queries with granular permissions. We use Hygraph when teams want a modern editorial UI, strong GraphQL ergonomics, and easy integration with other services through content federation, ideal for omnichannel content and multi-site setups.
LJX is our own custom CMS solution, designed to allow content editors to edit text in place. It provides a seamless editing experience, enabling users to make changes directly on the page without the need for separate editing tools.
OpenDXP (Open Data & Digital Experience Platform) is a community-driven fork of Pimcore Community Edition, made public in February 2026. It is forked from the last GPLv3 Pimcore CE release (v11.5.13) and is licensed under GPLv3 in perpetuity, preserving an open-source continuation of the platform after Pimcore's move to the source-available POCL license. It is architecturally faithful to Pimcore 11 (same Symfony foundation, same data-modeling approach, same admin-bundle UI model) and carries the full DXP scope: Product Information Management (PIM), Digital Asset Management (DAM), headless CMS, and composable commerce. The project is initiated and sponsored by DACHCOM.DIGITAL, a Swiss digital agency with a long history of Pimcore implementation work. We recommend OpenDXP for clients on established Pimcore Community Edition deployments who want to stay on GPLv3, avoid the Pimcore 12 license change and ExtJS admin-UI rewrite, and keep their existing copyleft dependencies legally compliant. Licensing notes: GPLv3 in perpetuity; community-governed; independent of and not endorsed by Pimcore GmbH.
Related reading: Pimcore or OpenDXP: A Fork in the Road for Long-Tenured DXP Stacks
An enterprise-grade platform that unifies Product Information Management (PIM), Digital Asset Management (DAM), headless CMS, and customer data capabilities in one stack. Pimcore shines when you need a single source of truth for complex catalogs, omnichannel content, and assets—powering consistent experiences across web, mobile, marketplaces, and POS. We choose Pimcore for data-heavy builds, multi-language catalogs, and intricate data modeling with strict governance. Its API-first approach pairs well with modern frontends (e.g., SvelteKit, Vue/Nuxt, Astro) and enables scalable, composable architectures without locking you into a single frontend or commerce engine. Licensing change (2025): Pimcore Community Edition moved from GPLv3 to the source-available Pimcore Open Core License (POCL). Version 2024.4 is the last GPLv3 CE release; 2025.1 and later are POCL. Pimcore 12 additionally removes the legacy ExtJS admin UI and requires replacing copyleft dependencies before upgrading. For teams that need to remain on GPLv3, the community fork OpenDXP continues the v11 codebase—see our analysis in the related reading below.
Related reading: Pimcore or OpenDXP: A Fork in the Road for Long-Tenured DXP Stacks
A highly customizable, schema-driven content platform with the Sanity Studio, real-time collaboration, and a powerful GROQ query language. Sanity’s Portable Text and content graph features enable flexible, structured content at scale. We choose Sanity when editorial workflows, real-time collaboration, and deep customization are priorities—especially for bespoke content models, multi-environment governance, and performant headless delivery. Licensing notes: SaaS with exportable content and APIs; bring-your-own CDN for assets if required.
Why this matters: Strong platform fundamentals (HTML, CSS, JS/TS) make apps faster, more accessible, and significantly easier to maintain. We ground every build in platform-native best practices: type-safe JavaScript, accessible HTML, and modern CSS. This foundation enables maintainable codebases, reliable refactors, and fast, inclusive user experiences. Preferred defaults: TypeScript strict mode; UnoCSS or Tailwind; semantic HTML with ARIA and WCAG 2.2 targets.
We leverage CSS Grid, Flexbox, custom properties, container queries, and cascade layers to build resilient layouts that adapt across devices. Our CSS approach centers performance, accessibility, and maintainability—minimizing specificity wars and dead code.
Semantic HTML is non-negotiable for accessibility, SEO, and performance. We prioritize ARIA correctness, keyboard navigability, and progressive enhancement. We follow best practices for metadata, link relations, preloading, and structured data to improve discoverability and UX.
Modern JavaScript features—modules, async/await, generators—paired with build tooling deliver lean bundles and clear, maintainable code. We emphasize performance practices like code-splitting, tree-shaking, and lazy-loading to optimize Core Web Vitals.
Our close second for utility-first styling. Tailwind enables consistent design systems, rapid iteration, and predictable theming with excellent tooling and ecosystem support. We pair Tailwind with component-driven UIs and design tokens for scalable, reusable patterns.
We default to TypeScript with strict mode wherever possible to enforce robust types, safer refactors, and reliable API contracts across services and clients. Our approach includes strict null checks, noImplicitAny, and type-safe schemas to reduce runtime errors and improve long-term maintainability.
Our preferred atomic CSS engine for on-demand utilities, instant compile, and flexible presets. UnoCSS keeps CSS minimal and maintainable while supporting design tokens and variants. We use it to balance developer velocity with runtime performance, avoiding unused styles and heavy bundles.
Why this matters: A reliable data layer is the backbone of performance, data integrity, and scale—without heavy ops overhead. Reliable data layers underpin fast, scalable web apps. We select managed, developer-friendly databases and storage that pair well with serverless/edge architectures, reduce ops overhead, and provide clear scaling paths. Preferred defaults: PlanetScale for MySQL workloads; Turso for edge-first SQLite; Upstash for Redis/queues; Vercel Blob for simple storage.
Scalable, S3-compatible object storage with a global CDN option and predictable pricing. Fits well when you need portable storage outside a specific hosting platform. We reach for Spaces for asset storage, backups, and static media distribution with familiar S3 tooling and lifecycle management.
Drizzle ORM is a TypeScript ORM for PostgreSQL, SQLite, MySQL, and CockroachDB
MySQL-compatible database built on Vitess, offering non-blocking schema changes, horizontal scaling, and branch-based workflows for safe migrations. We use PlanetScale for production-grade relational workloads that need MySQL semantics, strong reliability, and developer-friendly branching. Licensing notes: Managed MySQL (Vitess). Data export and branching facilitate migration when needed.
A high-performance Node.js image processing library powered by libvips—faster and more memory-efficient than ImageMagick/GD for common operations. We use Sharp to generate responsive variants, optimize to modern formats (WebP/AVIF), strip metadata, and enforce size constraints in upload pipelines and edge/serverless functions.
A distributed, edge-optimized SQLite database built on libSQL with global replicas for low-latency reads and serverless-friendly connections. We choose Turso for edge-first apps, multi-region reads, and lightweight relational workloads that benefit from SQLite ergonomics with cloud scale.
Pay-per-request, serverless data platform offering Redis, Kafka, QStash (HTTP-based queues), and vector storage with global latency optimization. We adopt Upstash for event streams, caching, queues, and lightweight vector/RAG needs in serverless and edge environments with minimal cold start overhead.
Simple, durable blob/object storage tightly integrated with Vercel projects and Edge Middleware. Great for uploads, public/private files, and serving media with minimal configuration. We use it for straightforward file storage in Vercel-hosted apps, leveraging built-in upload APIs, signed URLs, and region-aware performance.
Why this matters: The right framework reduces complexity and improves Core Web Vitals, which translates directly into better UX and SEO outcomes. Frontend frameworks are essential for building interactive and dynamic user interfaces. They provide a structured approach to organizing code, managing state, and handling user interactions. Preferred defaults: SvelteKit for app-first builds; Astro for content-heavy sites; Nuxt when teams prefer Vue.
A modern web framework focused on delivering zero-JS by default to the browser, Astro excels at content-rich sites with outstanding performance and supports Island Architecture so you can hydrate only what you need. Its seamless integration with React, Vue, Svelte, and others plus first-class MDX/content tooling make it a great fit for fast marketing sites, blogs, and documentation.
Our favorite open-source JavaScript framework at present, SvelteKit is the backbone of most of our new and upcoming projects. SvelteKit is the rare framework that truly reduces complexity and unpredictability rather than adding more limitations, complexity, or unnecessary boilerplate.
A progressive, approachable framework for building rich interfaces, with a gentle learning curve and excellent developer experience. Nuxt adds first-class routing, server rendering, API routes, and file-based conventions, ideal for content-driven sites, SSR/SSG, and hybrid apps. We reach for Vue/Nuxt when teams value clear component patterns, robust ecosystem support, and strong performance with minimal configuration.
Why this matters: Observability and tests catch regressions early, reduce MTTR, and enable confident, frequent releases. We ship with confidence by instrumenting apps end-to-end: unit and integration tests, accessibility checks, and production observability. Our approach emphasizes fast feedback loops, clear failure signals, and actionable telemetry. Preferred defaults: Sentry for errors/perf, Playwright for E2E, Vitest or Bun Test for unit, OpenTelemetry for tracing, Lighthouse CI for budgets.
Automated accessibility checks integrated into unit/E2E tests and CI to catch common WCAG issues early. We combine automated checks with manual screen reader and keyboard testing for comprehensive coverage.
All-in-one formatter, linter, and code actions replacement for ESLint/Prettier with native TypeScript support and very fast performance. We enforce strict TypeScript rules, import/order hygiene, and consistent formatting via Biome in CI for healthy, maintainable codebases.
Bun’s built-in test runner delivers extremely fast execution, snapshots, and watch mode—great for local DX and monorepos. We use Bun test where projects already target Bun for dev to get near-instant feedback loops.
We recommend feature flags and gradual rollouts to mitigate risk and enable safe experimentation. Tools like LaunchDarkly or Unleash pair with observability to quickly roll back or dial traffic.
Visit Change Tracking & Feature Flags →
We use Fallow for codebase intelligence on TypeScript and JavaScript projects—detecting dead code (unused files, exports, and dependencies), surfacing duplication before it spreads, and scoring complexity and health to prioritize refactoring. Fallow runs as a CLI, a VS Code extension, and an MCP integration for coding agents, so the same analysis is available in CI, in the editor, and to AI assistants. An optional paid runtime-intelligence layer adds production hot/cold path data as evidence for safe deletions.
Automated audits for Core Web Vitals, accessibility, SEO, and best practices in CI with historical tracking and budgets. We set performance budgets and fail builds when regressions exceed thresholds.
Vendor-neutral tracing, metrics, and logging instrumentation to unify observability across services and runtimes. We emit spans from serverless and edge functions to correlate logs, errors, and performance throughout a request.
Plausible is a lightweight web analytics tool that provides insights into website traffic and user behavior.
Reliable cross-browser E2E tests with powerful auto-waiting, tracing, and test isolation. Works well in CI with parallelization and flakes control. We use Playwright for user-journey and regression tests, plus accessibility assertions and visual comparisons when needed.
A developer-focused browser for multi-view responsive design, accessibility audits, and performance insights—all side by side. We use Polypane to validate layouts across breakpoints simultaneously, run a11y checks, visualize landmarks/headings, and preview meta/OG cards efficiently.
We validate API inputs/outputs and webhook payloads with schema libraries (e.g., Zod, Valibot) to stop bad data at boundaries. Schemas double as client contracts and improve testability. See “API & Integration → Schema Definition & Validation” for our defaults.
Visit Runtime Validation (Schemas at the Edges) →
Transaction tracing, N+1 detection, slow endpoint surfacing, and frontend interaction-to-backend correlation. We use sampling strategies to control costs while preserving actionable signal.
Visit Sentry Performance + Profiling →
Real-time error tracking, performance monitoring, and release health with source maps and stack traces across frontend, backend, and edge. We use Sentry for alerts, session replay, and tracing to quickly diagnose issues and correlate them to releases and commits.
UptimeRobot is a free uptime monitoring service that checks your website or service every minute and alerts you if it goes down.
A fast, Vite-native test runner with first-class TypeScript and ESM support. Ideal for component/unit tests and server logic with speedy watch mode. We pair Vitest with Testing Library for DOM tests and use coverage thresholds to protect critical paths.