The hidden cost of "getting started"
Picture this: You're a developer at a large tech company. Your team needs to build a new app or service. You know exactly what it should do, but first, you need to set up authentication, logging, monitoring, testing frameworks, linting rules, and ensure it follows company standards.
Sound familiar?
By the time you write your first line of business logic, two weeks have passed. Your "simple" application now has dozens of configuration files, and you're not even sure if you've set everything up correctly. Worse yet, the team down the hall is going through the exact same painful process.
At GoDaddy, we faced this challenge across many apps and services. Every team was reinventing the wheel, spending weeks on boilerplate setup instead of delivering value to customers. We needed a solution that would let developers go from idea to production-ready in hours, not weeks.
This is the problem Gasket solves.
What is Gasket?
Gasket is what we call a "Framework Maker": not just another framework, but a system for composing frameworks tailored to your organization's needs. Think of it as a plugin-powered platform that brings together all the tools and standards your teams need, while staying flexible enough to handle diverse use cases.
Here's the key insight: most organizations don't need another opinionated framework. They need a way to encode their own opinions, standards, and best practices into a reusable system that evolves with their needs.
How GoDaddy uses Gasket at scale
To understand why we built Gasket, you need to understand the scale at which GoDaddy operates. We're not just the world's largest domain registrar, with over 84 million domains registered. We power millions of small businesses with everything from hosting and email to website builders and online stores.
This means hundreds of internal apps and services, each with its own requirements. Before Gasket, each team faced the same challenges. Setting up a new service meant configuring build tools, establishing logging patterns, implementing authentication, and ensuring compliance with company standards. Teams were duplicating effort across the organization, each solving the same problems in slightly different ways.
The impact of Gasket has been transformative:
- Dramatically reduced service setup time
- More consistent deployments through standardized application structure
- Lighter applications with Gasket v7's removal of CLI dependencies
- Measurable increases in team velocity and developer productivity
But the real magic isn't in the metrics; it's in what happens when developers stop fighting boilerplate and start solving business problems. New team members become productive faster, experienced developers spend more time on innovation, and the entire organization benefits from shared solutions.
From internal tool to open source powerhouse
Gasket didn't start as a grand vision. It began with a simple observation: every team at GoDaddy was solving the same problems in slightly different ways. We had dozens of "starter kits" and "boilerplate repositories" floating around, each encoding someone's idea of best practices.
The breakthrough came when we stopped trying to build the "perfect" framework and started building a framework for making frameworks. Instead of prescribing solutions, Gasket provides the infrastructure for sharing and composing them.
What started as an internal solution to help GoDaddy's development teams ended up powering apps and services across the company at significant scale. This success convinced us other organizations facing similar challenges could benefit from the same approach.
The plugin architecture that changed everything
At its core, Gasket is deceptively simple. It's a plugin system with lifecycles - specific points where plugins can hook in to change behavior. But this simplicity enables powerful composition.
The following code shows how a basic Gasket application combines different plugins to create a fully functional app:
// A basic Gasket app in v7
import { makeGasket } from '@gasket/core';
import pluginNextjs from '@gasket/plugin-nextjs';
import pluginLogger from '@gasket/plugin-logger';
import pluginAuth from '@your-company/gasket-plugin-auth';
export default makeGasket({
plugins: [
pluginNextjs, // Adds Next.js support
pluginLogger, // Adds structured logging
pluginAuth // Your custom auth solution
]
});

The Gasket v7 architecture: Plugins integrate through a central registry, expose actions via GasketActions API, and coordinate through lifecycle hooks
What makes this powerful is that each plugin can:
- Add dependencies to your project
- Configure build tools
- Set up middleware
- Define new commands
- Hook into other plugins' lifecycles
This means your custom authentication plugin can automatically configure itself to work with the logging plugin, which integrates with your monitoring plugin, and so on. It's composition all the way down.
Presets: frameworks within the framework
While plugins provide features, presets provide opinions. A preset is simply a collection of plugins pre-configured to work together.
The following example shows what's included in common Gasket presets:
// @gasket/preset-nextjs includes:
// - Next.js plugin
// - Webpack plugin
// - Intl plugin
// - Production-ready configurations
// @your-company/preset-api might include:
// - Express/Fastify plugin
// - Your auth plugin
// - Your monitoring standards
// - Your API conventions
This two-level architecture (plugins for capabilities, presets for opinions) lets organizations encode their standards without losing flexibility. Teams get started quickly with presets but can always add or customize plugins as needed.
What makes Gasket different?
In a world full of JavaScript frameworks, what makes Gasket special? It's not about competing with Express, Next.js, or Fastify; it's about making them work better together.
Traditional frameworks ask: "What's the best way to build apps?" Gasket asks: "What's the best way for YOUR team to build apps?"
Instead of prescribing patterns, Gasket provides the infrastructure to encode and share your patterns. This fundamental difference changes everything:
Traditional Framework | Gasket Approach |
---|---|
"Use our router" | "Choose Express, Fastify, or bring your own" |
"Follow our file structure" | "Define your own conventions via plugins" |
"Learn our testing approach" | "Use Jest, Mocha, Vitest (whatever fits)" |
"Adopt our deployment model" | "Integrate with your existing pipelines" |
Lifecycle-driven architecture
Gasket's lifecycle system is what makes plugin composition possible. Each lifecycle represents a specific moment in your app's journey: from build time to request handling.
The following code demonstrates how an authentication plugin can hook into different lifecycle events:
export default {
name: 'my-security-plugin',
hooks: {
// Build-time: Add security headers to webpack
webpackConfig(gasket, config) {
return addSecurityHeaders(config);
},
// Start-time: Set up security middleware
express(gasket, app) {
app.use(securityMiddleware);
},
// Request-time: Validate permissions
async middleware(gasket) {
return async function validateMiddleware(req, res, next) {
await validatePermissions(req);
next();
}
}
}
};
This isn't just about organizing code; it's about creating predictable integration points where plugins can cooperate without tight coupling.
Progressive disclosure of complexity
One of Gasket's core principles is meeting developers where they are. New developers can start with a simple command:
npx create-gasket-app my-app --presets @gasket/preset-nextjs
The interactive prompts guide them through the setup, making sensible defaults available while allowing customization where needed. Once created, starting the app is straightforward:
cd my-app
npm run local
They now have a working Next.js app with best practices baked in. But when they need to customize something, the full power is there:
- Start with presets
- Add individual plugins as needed
- Create custom plugins for your needs
- Share plugins across teams
- Eventually create your own presets
The Gasket development journey: Start simple, add complexity only as needed, iterate without friction
This progression from consumer to contributor happens naturally as teams grow.
Gasket in action
Now that you understand Gasket's philosophy and approach, let's see how it translates into real code. We'll build two different solutions to showcase its flexibility and show how quickly you can go from zero to production-ready.
Building an API with @gasket/preset-api
Want to build a production-ready API? Here's how simple the process is:
# Create the app
npx create-gasket-app weather-api --presets @gasket/preset-api
The create command will walk you through a series of choices to tailor the app to your needs:
? What is your app description?
? Which packager would you like to use? (npm/yarn/pnpm)
? Do you want to use Vitest for unit testing?
? Do you want to use TypeScript?
? Do you want to use Swagger?
? Which server framework would you like to use? (Express/Fastify)
? Do you want to use generated documentation?
? Do you want a git repo to be initialized?
? Which code style do you want configured?
After answering these prompts, Gasket sets up your project with all your selections properly configured. In just a few minutes, you have a working API with:
- Express or Fastify configured
- Structured logging via Winston
- Health checks and monitoring
- Swagger documentation
- Production-ready error handling
- Environment configuration support
Let's add a simple endpoint:
// plugins/weather-api.js
export default {
name: 'weather-api',
hooks: {
express(gasket, app) {
app.get('/api/weather/:city', async (req, res) => {
const { city } = req.params;
const logger = gasket.actions.getLogger();
logger.info('Weather request', { city });
// Your weather logic here
const weather = await getWeatherData(city);
res.json(weather);
});
}
}
};
// gasket.js
import { makeGasket } from '@gasket/core';
import weatherApi from './plugins/weather-api.js';
export default makeGasket({
plugins: [
// Other plugins...
weatherApi
]
});
// server.js
import gasket from './gasket.js';
// Fire up the server (this spins up Express or Fastify for you)
gasket.actions.startServer();
That's it. You have logging, error handling, monitoring, and documentation, all from those few lines.
Building a Next.js app with @gasket/preset-nextjs
For full-stack applications, the Next.js preset provides a comprehensive setup:
npx create-gasket-app customer-portal --presets @gasket/preset-nextjs
Like the API preset, prompts guide you through configuration choices specific to Next.js applications, including testing frameworks, TypeScript preferences, and styling options. Once configured, you get:
- Next.js with App or Page Router support (
@gasket/plugin-nextjs
) - Internationalization (i18n) ready (
@gasket/plugin-intl
) - Performance monitoring (
@gasket/plugin-elastic-apm
) - SEO optimizations (built into Next.js)
- Progressive Web App capabilities (
@gasket/plugin-manifest
,@gasket/plugin-service-worker
,@gasket/plugin-workbox
) - TypeScript support (optional) (
@gasket/plugin-typescript
)
Here's how you'd add authentication using GasketActions:
// api/validate.js
import gasket from '../../../gasket';
export default async function GET(req, res) {
// Validate auth with a GasketAction
const authResults = gasket.actions.checkAuth(req);
res.json(authResults);
}
// pages/secure-page.js
import React from 'react';
import gasket from '../gasket';
function SecurePage({ secretData }) {
return (
<div>
<h1>Secret Data</h1>
<pre>{JSON.stringify(secretData, null, 2)}</pre>
</div>
);
}
SecurePage.getInitialProps = async ({ req, res }) => {
let authResults
if (req) {
// Validate auth on the server with the GasketAction
authResults = gasket.actions.checkAuth(req);
if (!authResults.valid) {
res.writeHead(302, {Location: '/login'});
res.end();
return {
secretData: null
}
}
} else {
// On the client, call our auth validation API route
authResults = await fetch('/api/validate').then(r => r.json());
if (!authResults.valid) {
window.location.href = '/login';
return {
secretData: null
}
}
}
// If authenticated, fetch some protected data
const secretData = await fetch('https://api.example.com/secret-data', {
headers: {
'Authorization': `Bearer ${authResults.token}`
}
}).then(r => r.json());
return {
secretData
}
};
export default SecurePage;
Notice how GasketActions provide a consistent interface for accessing functionality, whether you're in an API route or a React component. No more prop drilling or context wrapping; just call the action you need.
The plugin architecture: Building blocks of innovation
Think of Gasket plugins like LEGO blocks: each one does something specific, but they're designed to work together. The magic happens when you combine them.
Anatomy of a plugin
A Gasket plugin is just a JavaScript object with a specific shape:
export default {
name: '@your-company/gasket-plugin-analytics',
// Hook into Gasket lifecycles
hooks: {
// Add analytics script to the build
webpackConfig(gasket, config) {
config.plugins.push(new AnalyticsPlugin());
return config;
},
// Track server startup (runs once after plugins are initialized)
async init(gasket) {
await gasket.actions.trackEvent('server_started', {
environment: gasket.config.env
});
}
},
// Provide actions other code can use
actions: {
async trackEvent(gasket, eventName, data) {
// Your analytics logic here
}
}
};
How plugins compose
The real power comes from how plugins work together. Let's say you have three plugins:
- Authentication Plugin: Handles user authentication
- Analytics Plugin: Tracks user behavior
- Feature Flag Plugin: Controls feature access
They can seamlessly integrate:
// feature-flag-plugin.js
export default {
name: 'feature-flag-plugin',
actions: {
/**
* Check if the visitor has a particular feature.
*/
async hasFeature(gasket, req, featureName) {
const visitor = await gasket.actions.getVisitor(req); // From visitor plugin
const features = await getFeatureFlags(visitor);
await gasket.actions.trackEvent('feature_accessed', {
visitorId: visitor.id,
feature: featureName
});
return features.includes(featureName);
}
}
};
No explicit dependencies. No tight coupling. Just plugins using each other's actions and respecting lifecycle order.
Lifecycle timing is the secret sauce
What prevents chaos when many plugins hook the same lifecycle? Timing controls:
export default {
name: 'my-plugin',
hooks: {
middleware: {
timing: {
after: ['@gasket/plugin-auth'], // Run after auth
before: ['@gasket/plugin-logger'] // But before logging
},
handler(gasket, app) {
// Your middleware logic
}
}
}
};
This declarative approach means:
- Plugins don't need to know about each other's internals
- Order of operations is explicit and debuggable
- New plugins can insert themselves anywhere in the chain
Less magic, more transparency with Gasket v7
Version 7 represents our biggest philosophical shift yet. We asked ourselves: what if we removed every bit of "magic" that makes debugging harder or learning curves steeper?
The great CLI removal
The boldest change? We removed the Gasket CLI entirely. Here's why:
Before (v6):
gasket build # What webpack config is it using?
gasket start # How is the server configured?
gasket local # What's different from start?
Every command was a black box. Debugging meant diving into Gasket's internals.
After (v7):
next build # Using Next.js? Use Next.js commands
npm run build # Custom build? See package.json
node server.js # Start server? Just run it
This transparency has transformed the developer experience. Engineers now understand exactly what's happening at every step. Debugging is straightforward because there's no abstraction layer hiding the real commands. New developers familiar with Next.js or Express can immediately understand and change Gasket applications without learning proprietary CLI commands.
The end of request decoration with GasketActions
Remember the bad old days of decorated request objects?
// The old way (v6)
app.use(async (req, res, next) => {
req.user = await getUser(req);
req.permissions = await getPermissions(req.user);
req.features = await getFeatures(req.user);
req.logger = getLogger(req);
// Is req.user available in the next middleware? 🤷
next();
});
Every middleware added mystery properties. TypeScript couldn't help. Debugging was complex.
With GasketActions in v7:
// The new way (v7)
app.get('/api/data', async (req, res) => {
const user = await gasket.actions.getUser(req);
const permissions = await gasket.actions.getPermissions(req);
const features = await gasket.actions.getFeatures(req);
const logger = gasket.actions.getLogger();
// Explicit. Typed. Debuggable.
});
Performance improvements that matter
The "less magic" approach brought unexpected benefits:
- Smaller application footprint: Removing the CLI and its dependencies reduces the package size
- Faster startup times: Direct execution removes command parsing overhead
- Better tree shaking: ESM-first design allows build tools to remove dead code more effectively
- Improved debugging: Standard Node.js tools work without interference from abstraction layers
These improvements compound in production environments. Lighter applications mean less to download and install. Faster startup times improve scaling responsiveness. Better tree shaking reduces bandwidth usage and improves application performance.
Modern JavaScript, finally
Gasket v7 embraces modern standards:
// ESM modules by default
import { makeGasket } from '@gasket/core';
import pluginNext from '@gasket/plugin-nextjs';
// Top-level await
const gasket = makeGasket({ plugins: [pluginNext] });
await gasket.ready;
// Direct framework integration
export default await gasket.actions.getNextConfig();
No more CommonJS/ESM translation layers. No more build tool magic. Just modern JavaScript that runs everywhere.
How does Gasket compare?
Let's address the elephant in the room: how does Gasket stack up against other popular frameworks? The answer might surprise you: we're not competing with them. We're making them better.
The apples and oranges problem
Comparing Gasket to Express, Fastify, or NestJS is like comparing a toolkit to a hammer. They solve different problems:
Framework | What It Does | Best For |
---|---|---|
Express | Minimal web framework | Simple APIs, most flexibility |
Fastify | High-performance web framework | Speed-critical services |
NestJS | Enterprise application framework | Large, structured applications |
Gasket | Framework maker | Making any of the above work better for your org |
Gasket doesn't replace these frameworks; it enhances them.
Build your own vs. Gasket
The actual alternative to Gasket isn't another framework; it's building your own platform from scratch. Here's what that looks like:
Challenge | DIY Approach | Gasket Approach |
---|---|---|
Initial Setup | Weeks of boilerplate | npx create-gasket-app |
Sharing Standards | Copy-paste templates | Plugins and presets |
Updates | Manually update each service | Update plugin version |
Onboarding | Long documentation | Working app in minutes |
Flexibility | Rewrite for changes | Add/remove plugins |
GoDaddy's Gasket success story
What started as an experiment to reduce boilerplate has become the foundation for our entire Node.js ecosystem.
The benefits of Gasket are evident across every dimension of our development process:
Development Velocity:
Engineers can now go from initial idea to production-ready code in a fraction of the time required before. This acceleration means teams spend their time solving business problems rather than wrestling with configuration and setup.
Team Productivity:
Engineers can now effectively maintain many services thanks to the consistency Gasket provides. The cognitive load of switching between projects has decreased dramatically because every Gasket application follows familiar patterns. This standardization has freed engineers to focus on features rather than infrastructure.
From internal tool to open source
Gasket's success at GoDaddy led to a natural question: could this help other organizations facing similar challenges?
We're excited to see how the open-source community will continue to embrace Gasket, with developers from diverse organizations making contributions. We envision an ecosystem that grows beyond our initial scope — with community-driven plugins for GraphQL, Vite, Svelte, and more. Through collaboration, Gasket can become more robust and versatile than we could have achieved alone.
The GitHub repository continues to grow, attracting developers who recognize the value of a framework-making approach. Our aim is for Gasket to help organizations of all sizes standardize their Node.js development — and to show that the challenges we faced at GoDaddy are ones many modern teams can relate to.
Get started with Gasket
The beauty of Gasket is that you don't need to transform your entire organization to see benefits. Start small, prove the value, and grow from there.
Start your journey
For Individual Developers:
- Build your next side project with Gasket
- Experience the productivity boost firsthand
- Share your experience with your team
For Teams:
- Start with one new app or service
- Create your first shared plugin
- Document your patterns
- Share across projects
For Organizations:
- Identify common patterns across teams
- Build organizational presets
- Establish your platform standards
- Enable teams to move faster
Join the community
Gasket is more than code: it's a community of developers solving similar problems:
- GitHub: github.com/godaddy/gasket - Star, contribute, or report issues
- Documentation: gasket.dev - Comprehensive guides and API docs
The future is composable
At GoDaddy, Gasket has fundamentally changed how we think about building services. Instead of asking "how do we build this?", we ask "what plugins do we need?" Instead of reinventing wheels, we're composing solutions
Gasket v7's "less magic" philosophy makes it easier than ever to adopt. There's no mysterious CLI to learn, no hidden behaviors to debug. Just compose the plugins you need, and let your framework do what it does best.
Whether you're a solo developer tired of boilerplate, a team lead looking to standardize practices, or an architect designing for scale, Gasket provides the foundation for building better, faster, and more maintainable applications.
Ready to transform how your team builds applications? Start with Gasket today and join the growing community of developers who've discovered a better way to build.
npx create-gasket-app
Welcome to the future of framework making.