# Introduction ## Welcome to ShipAhead ShipAhead is a modern, fast, and fully customizable SaaS starter kit built to help you launch apps without wasting time on boilerplate. This guide introduces the core concepts and tech powering ShipAhead so you know what’s under the hood. ## Tech Stack ShipAhead is built with a focus on performance, flexibility, and scalability. Here’s what’s included: - **Frontend**: Nuxt 4, Vue, Tailwind CSS, Nuxt UI - **Internationalization (i18n)**: Nuxt i18n - **Analytics**: Umami, Datafast, Google Analytics - **Authentication**: Better Auth (Email/Password, Magic Link, OAuth) - **Database**: Drizzle ORM & PostgreSQL (Supabase, Neon, or any PostgreSQL connection string) - **Storage**: Cloudflare R2 or S3 via aws4fetch - **Email**: Resend & Vue Email - **Payments**: Stripe, Polar, Dodo Payments - **AI**: OpenRouter AI - **PWA**: Vite PWA - **Deployment**: Vercel, Cloudflare # Setup ## Prerequisites Make sure you have these installed: - **[Node.js](https://nodejs.org/en/download/)** – Version 22.x or higher (includes npm). - **[Git](https://git-scm.com/install/)** – For version control. - **[Cursor](https://cursor.com)** or **[VSCode](https://code.visualstudio.com/)** – For editing your code. ## Setup in 5 Minutes ### 1. Clone the Repository You have three ways to get a copy: 1. **Fork + Clone** Fork the repo on GitHub, then clone your fork: ```text \[Terminal] git clone https://github.com/your-username/shipahead-template.git your-project-name ``` 2. **Use Template** Click **Use this template** on the ShipAhead repo to create a new repository, then clone it. 3. **Direct Clone** ```text \[Terminal] git clone https://github.com/Tom-Han-Org/shipahead-template.git your-project-name cd your-project-name ``` ### 2. Install Dependencies Run this to install everything the project needs: ```text [Terminal] npm install ``` ### 3. Configure Your Project - **Environment Variables** Copy the example file and update it with your settings (database URLs, API keys, etc.): ```text \[Terminal] mv .env.example .env ``` :brOpen `.env` in a text editor and fill in your values. - **App Configuration** Customize your app name, feature toggles, and other settings in `shared/config.ts`. ### 4. Run the Development Server Start your app locally: ```text [Terminal] npm run dev ``` Visit [](http://localhost:3000){rel=""nofollow""} – your app is live! 🎉 ## Pull Updates Keep your project in sync with the latest ShipAhead changes: ```text [Terminal] git remote add upstream https://github.com/Tom-Han-Org/shipahead-template.git git fetch upstream git merge upstream/main ``` > **Tip**: If there are merge conflicts, review and resolve them manually. # Database ## Tools - **[Drizzle ORM](https://orm.drizzle.team)**: Provides a lightweight, type-safe way to interact with PostgreSQL databases. ## Setup 1. Sign up / Sign in for a PostgreSQL database at [Supabase](https://supabase.com), [Neon](https://neon.com), or another provider. 2. Copy the **Database URL / Connection String** from your provider’s dashboard (e.g., `postgres://user:password@host:port/dbname`). 3. Set environment variable: ```text \[.env] DATABASE_URL="your-postgresql-database-url" ``` 4. Generate schema migrations: ```text \[Terminal] npm run db:generate ``` 5. Apply migrations to your database: ```text \[Terminal] npm run db:migrate ``` ## Usage - **Database Connection**: The database is initialized in `server/db/init.ts` using `DATABASE_URL` and connects to tables defined in `server/db/schema/`. - **Query Data**: Use Drizzle ORM in server services, e.g., insert records. ```text \[server/service/contact.ts] import { useDatabase } from '~~/server/db/init'; import * as schema from '~~/server/db/schema'; export const contactServices = { async submit(body: { name: string; email: string; message: string }) { const db = useDatabase(); await db.insert(schema.contact).values({ id: crypto.randomUUID(), name: body.name, email: body.email, message: body.message, }); }, }; ``` - **Manage Schemas**: Update `server/db/schema/` to add or modify tables. Run `npm run db:generate` and `npm run db:migrate` after changes. - **Verify Setup**: Check your database provider’s dashboard (e.g., Supabase or Neon) to confirm tables are created. # Authentication ## Tools - **[Better Auth](https://www.better-auth.com)**: Provides secure authentication with email/password, OAuth, and magic link support. ## Setup 1. For Google OAuth, sign up at [Google Cloud Console](https://console.cloud.google.com/apis/credentials) and copy the **Client ID** and **Client Secret**. 2. Update your config: ```ts \[shared/config.ts] auth: { enablePasswordLogin: true, // Allow email/password login and registration enableEmailVerification: false, // Require email verification after signup enableMagicLink: false, // Allow passwordless login via email link oauthProviders: ['google'], // Enable Google OAuth redirectAfterSignIn: '/', // Where to redirect after successful login password: { minLength: 8, maxLength: 128, pattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/, }, }, ``` - **Note**: Add more OAuth providers (e.g., `github`, `twitter`, `apple`) to `oauthProviders` and set corresponding environment variables (e.g., `OAUTH_GITHUB_CLIENT_ID`, `OAUTH_GITHUB_CLIENT_SECRET`). 3. Set the following environment variables: ```text \[.env] BETTER_AUTH_SECRET="your-long-random-string" OAUTH_GOOGLE_CLIENT_ID="your-google-client-id" OAUTH_GOOGLE_CLIENT_SECRET="your-google-client-secret" ``` ## Usage - **Email/Password**: Sign in, sign up, reset password, sign out - **Google OAuth**: Sign in with Google account - **Magic Link**: Sign in via email link - **Verify Setup**: Use `user` and `loggedIn` from `useAuth` composable # Payments ## Setup ### Stripe 1. Sign up at [Stripe](https://dashboard.stripe.com/register) and create an account. 2. Create a **Product**in the Stripe Dashboard. - Add pricing plans (e.g. Monthly $10, Yearly $60). - Copy the **Price IDs** (they look like `price_xxx`). 3. Copy your **Secret Key** and **Webhook Secret** from the Stripe Dashboard (Developers > API Keys and Webhooks). 4. Set the following environment variables: ```text \[.env] STRIPE_SECRET_KEY="your-stripe-secret-key" STRIPE_WEBHOOK_SECRET="your-stripe-webhook-secret" ``` 5. Update pricing plans in your config: ```ts \[shared/config.ts] pricing: { paymentProvider: enums.paymentProvider.stripe, // Set paymentProvider Stripe successUrlPath: '/payment-success', // Redirect after successful payment failedUrlPath: '/payment-failed', // Redirect after failed payment plans: { pro: { enable: true, // Is show Pro Plan key: 'pro', monthly: { key: 'pro-monthly', priceId: 'price_monthly', // Set Stripe Price ID for monthly subscription mode: 'subscription', // Payment is subscription }, yearly: { key: 'pro-yearly', priceId: 'price_yearly', // Set Stripe Price ID for yearly subscription mode: 'subscription', // Payment is subscription }, }, lifetime: { enable: true, // Is show Lifetime Plan key: 'lifetime', priceId: 'price_lifetime', // Set Stripe Price ID for one-time payment promoCodeId: '', // Optional - Set Stripe Promo ID for any promo/coupon to discount mode: 'payment', // Payment is one-time }, }, }, ``` 6. Set up a webhook: - **Local**: Use [Stripe CLI](https://docs.stripe.com/stripe-cli){rel=""nofollow""} ```text \[Terminal] stripe listen --forward-to localhost:3000/api/auth/stripe/webhook ``` Copy the Webhook Secret into `.env`. - **Production**: Add a webhook endpoint in Stripe Dashboard pointing to: ```text https://your-site.com/api/auth/stripe/webhook ``` Select events like `checkout.session.completed`, `customer.subscription.created`, `customer.subscription.updated`, and `customer.subscription.deleted`. ### Polar 1. Sign up at [Polar](https://polar.sh) and create an account. 2. Create a **Product**in the Polar Dashboard. - Add pricing plans (e.g. Monthly $10, Yearly $60). - Copy the Product IDs (found in the product details/API settings). 3. Generate a **Personal Access Token** (or Organization Token) and configure a **Webhook** in the Polar Dashboard (Settings > Developers). 4. Set the following environment variables: ```text \[.env] POLAR_ACCESS_TOKEN="your-polar-access-token" POLAR_WEBHOOK_SECRET="your-polar-webhook-secret" ``` 5. Update pricing plans in your config: ```ts \[shared/config.ts] pricing: { paymentProvider: enums.paymentProvider.polar, // Set paymentProvider Polar successUrlPath: '/payment-success', // Redirect after successful payment failedUrlPath: '/payment-failed', // Redirect after failed payment plans: { pro: { enable: true, // Is show Pro Plan key: 'pro', monthly: { key: 'pro-monthly', priceId: 'price_monthly', // Set Polar Product ID for monthly subscription mode: 'subscription', // Payment is subscription }, yearly: { key: 'pro-yearly', priceId: 'price_yearly', // Set Polar Product ID for yearly subscription mode: 'subscription', // Payment is subscription }, }, lifetime: { enable: true, // Is show Lifetime Plan key: 'lifetime', priceId: 'price_lifetime', // Set Polar Product ID for one-time payment mode: 'payment', // Payment is one-time }, }, }, ``` 6. Set up a webhook: - **Local**: Use a tunneling service (like ngrok) or Polar's CLI if available to forward events to your local environment. Copy the Webhook Secret into `.env`. - **Production**: Add a webhook endpoint in Polar Dashboard pointing to: ```text https://your-site.com/api/auth/polar/webhooks ``` Select at least the following events like `order.created`, `subscription.created`, `subscription.updated`, `subscription.canceled`. ### Dodo Payments 1. Sign up at [Dodo Payments](https://app.dodopayments.com/login) and create an account. 2. Create a **Product**and its associated pricing plans in the Dodo Payments Dashboard. - Copy the **Product IDs** (they typically start with `pdt_`) for each unique plan/interval. 3. Copy your **API Key** and **Webhook Secret** from the Dodo Payments Dashboard (Developer > API Keys and Webhooks). 4. Set the following environment variables: ```text \[.env] DODO_PAYMENTS_API_KEY="your-dodo-api-key" DODO_PAYMENTS_WEBHOOK_SECRET="your-dodo-webhook-secret" ``` 5. Update pricing plans in your config: ```ts \[shared/config.ts] pricing: { paymentProvider: enums.paymentProvider.dodo, // Set paymentProvider Dodo successUrlPath: '/payment-success', // Redirect after successful payment failedUrlPath: '/payment-failed', // Redirect after failed payment plans: { pro: { enable: true, // Is show Pro Plan key: 'pro', monthly: { key: 'pro-monthly', priceId: 'price_monthly', // Set Dodo Product ID for monthly subscription mode: 'subscription', // Payment is subscription }, yearly: { key: 'pro-yearly', priceId: 'price_yearly', // Set Dodo Product ID for yearly subscription mode: 'subscription', // Payment is subscription }, }, lifetime: { enable: true, // Is show Lifetime Plan key: 'lifetime', priceId: 'price_lifetime', // Set Dodo Product ID for one-time payment mode: 'payment', // Payment is one-time }, }, }, ``` 6. Set up a webhook: - **Local**: Use a tunneling service (like ngrok) to expose your local development server. ```text \[terminal] # Example using ngrok to tunnel to your app's port ngrok http 3000 ``` Copy the resulting URL and add /api/payment/dodo/webhook to it for the Dodo Webhook configuration. - **Production**: Add a webhook endpoint in Dodo Payments Dashboard pointing to: ```text https://your-site.com/api/payment/dodo/webhook ``` Select at lease the following events like `payment.succeeded`, `payment.failed`, `subscription.active`, `subscription.updated`, `subscription.renewed`, `subscription.cancelled`, `subscription.on_hold`, and `subscription.failed`. ## Usage - **Handle Webhooks**: Plugin automatically updates subscription status on payment events. - **Verify Payments**: Check transactions and subscriptions in the plugin dashboard. - **Initiate Checkout**: Use the `paymentCheckout`function to start a payment. ```vue const { payment } = useAuth(); payment.paymentCheckout(appConfig.pricing.plans.lifetime.key, locale.value); ``` Users are redirected to payment's checkout page, then back to `successUrlPath` or `failedUrlPath` - **Customer Portal**: Let users manage subscriptions, invoices, and payment methods: ```vue const { payment } = useAuth(); payment.toCustomerPortal(); ``` # Admin Panel ## Setup To seed an Admin account, follow these steps: 1. Open the script `scripts/seed-admin-manual.cjs` and configure the new admin details: ```text \[scripts/seed-admin-manual.cjs] const newAdmin = { email: 'your_admin@yourdomain.com', password: 'your-secure-password', name: 'Your Admin Name', role: 'admin', } ``` 2. Run the command to create the admin: ```text \[Terminal] npm run seed:admin ``` ## Usage The Admin Panel dashboard is available at `/admin` (accessible only to users with the `admin` role). ### Dashboard - **Stats**: Displays total users, admins, members, and new signups (last 7 days). ### User Management - **List Users**: View all users with pagination and filter by name. - **Edit User Status**: Update a user’s status to **Active** or **Banned**. - **Create New User**: Add a new user by filling in name, email, role, and password (restricted to admins). # AI Integration with OpenRouter ## Tools - **[OpenRouter](https://openrouter.ai)** – Access multiple AI models for chat, text, and images. ## Setup 1. Sign up at [OpenRouter](https://openrouter.ai). 2. Create an **API Key** in Account → API Keys. 3. Add the environment variable: ```env.local OPENROUTER_API_KEY="your-openrouter-api-key" ``` 4. Select your default model in the config: ```ts \[shared/config.ts] ai: { model: 'openai/gpt-4o', // You can switch to any model from openrouter.ai/models }, ``` ## Usage ShipAhead includes ready-to-use AI pages so you don’t have to code: - **AI Chat** – `/app/pages/ai/chat.vue`:br A ready made chat interface powered by your configured AI model. - **AI Text Generator** – `/app/pages/ai/text.vue`:br Enter text, generate output, and see results instantly. The API prompt and user input are combined in one request. - **AI Image Generator** – `/app/pages/ai/image.vue`:br Generate images from prompts using supported models. # Customization ## Setup 1. **Logo** - Create a logo (PNG, \~50×50px recommended) - Save to: ```text public/images/logo.png ``` - Update your config: ```ts \[shared/config.ts] brandingImages: { logo: '/images/logo.png', openGraphImage: '/images/open-graph.png', }, ``` 2. **Open Graph Image (Social Preview)** - Create an OG image using [Canva](https://www.canva.com) or [OG Image Generator](https://www.og-image-generator.com/). - Recommended size: **1200×630px** - Save to: ```text public/images/open-graph.png ``` 3. **Favicon** - Generate favicon assets using [Favicon.io](https://favicon.io/favicon-converter/). - Place them in `public/images/`: - `android-chrome-512x512.png` → `pwa-icon-48x48.png` - `android-chrome-192x192.png` → `pwa-icon-192x192.png` - `android-chrome-512x512.png` → `pwa-icon-512x512.png` - `apple-touch-icon.png` - `favicon.ico` 4. **Font Family** - Choose a font and apply it globally: ```css \[app/assets/styles/main.css] @theme { --font-sans: 'Inter', sans-serif; } ``` 5. **Theme (Radius & Colors)** - Radius: ```css \[app/assets/styles/main.css] :root { --ui-radius: 0.5rem; } ``` - Colors: ```ts \[app/app.config.ts] ui: { colors: { primary: 'blue', neutral: 'neutral', }, }, ``` 6. **Icons (Icones.js)** - Browse icons at icones.js.org and use the icon name in your components: ```vue ``` ## Usage - Run `npm run dev` to preview changes - Verify logo, favicon, fonts, and theme in the browser - Use a social preview checker to confirm the OG image - **UI Components**: For customizing UI elements (buttons, cards, modals, etc.), refer to the [NuxtUI](https://nuxtui.com/docs/components/) # Storage ## Tools - [Cloudflare R2](https://www.cloudflare.com/products/r2) – simple and cost-effective storage (recommended) - [AWS S3](https://aws.amazon.com/s3) (or any S3-compatible service) – more advanced features ## Setup 1. Choose a storage provider: - [Cloudflare R2](https://www.cloudflare.com/products/r2) – recommended for simplicity and low cost - [AWS S3](https://aws.amazon.com/s3) (or compatible services like MinIO, DigitalOcean Spaces, etc.) 2. Create a bucket: - Go to your provider’s dashboard and create a new bucket (folder for files) - Copy the **credentials**: access key, secret key, bucket name, endpoint 3. Cloudflare R2 specific steps: 1. Sign up / Sign in at [Cloudflare](https://www.cloudflare.com/products/r2) 2. Create a new R2 bucket: - Pick a globally unique bucket name (e.g., `your-project-name`) - Select a region close to your target audience 3. Enable public access: Settings → Public Development URL → Enable - Save the public URL as `STORAGE_PUBLIC_URL` - Optional: Set custom domains for added security 4. Create a new API Token: - Storage & databases > R2 object storage > API Tokens > Manage, click Create User API Token - Set permissions to Object Read & Write to the bucket - Copy the Access Key ID and Secret Access Key 4. Set the following environment variables: ```text \[.env] S3_REGION="your-region" # Use "auto" for R2, or e.g. "us-east-1" for S3 S3_BUCKET="your-bucket-name" S3_ACCESS_KEY_ID="your-access-key-id" S3_SECRET_ACCESS_KEY="your-secret-access-key" S3_ENDPOINT="your-s3-endpoint" # Optional S3_PUBLIC_URL="https://cdn.yourdomain.com" # Public URL (CDN or subdomain) ``` ## Usage Storage functions are available in the File Management module in the Admin Panel. Use the `useApi` composable: - **List files**: ```text \[app/pages/admin/files.vue] const { getStorageFiles } = useApi(); const response = await getStorageFiles(); console.log('File uploaded list:', response.data.blobs); ``` - **Upload files**: ```text \[app/pages/admin/files.vue] const { uploadStorageFiles } = useApi(); const selectedFiles = ref([]); const response = await uploadStorageFiles(selectedFiles.value); console.log('File uploaded total:', response.data.success); ``` - **Download a File**: ```text \[app/pages/admin/files.vue] const { downloadStorageFile } = useApi(); const file = await downloadStorageFile('example.jpg'); ``` - **Delete a File**: ```text \[app/pages/admin/files.vue] const { deleteStorageFile } = useApi(); const response = await deleteStorageFile('example.jpg'); console.log('Deleted?', response.success); ``` - **Bulk delete files**: ```text \[app/pages/admin/files.vue] const { bulkDeleteStorageFile } = useApi(); const response = await bulkDeleteStorageFile(['example.jpg']); console.log('Deleted Total: ', response.data.success); ``` - **Access public file (CDN)**: ```text \[app/pages/admin/files.vue] const { public: pub } = useRuntimeConfig(); const imageUrl = `${pub.storagePublicUrl}/example.jpg`; console.log(imageUrl); // https://cdn.yourdomain.com/example.jpg ``` ## Best Practices - File Size Limits: Set reasonable file size limits to prevent abuse - File Type Validation: Validate file types on both client and server sides for security # Email ## Tools - **[Resend](https://resend.com)**: Handles sending transactional emails reliably. - **Cloudflare Email**: An alternative for sending transactional emails. - **[Maizzle](https://maizzle.com)**: Create responsive HTML emails with Tailwind CSS. ## Setup ### Resend 1. Sign up at [Resend](https://resend.com). 2. Go to API Keys to create an API Key. Fill in the name you like and keep other options as default. Then click add and copy the **API Key** . 3. Set environment variable: ```text \[.env] RESEND_API_KEY="your-resend-api-key" ``` 4. Go to Domains and add your sending domain (recommended: a subdomain, e.g., resend.yourdomain.com) and complete DNS verification. 5. Update your config: ```ts \[shared/config.ts] email: { provider: enums.emailProvider.resend, // Set email provider Resend senderName: "Your Name from Which App", senderEmail: "no-reply@resend.yourdomain.com", }, ``` ### Cloudflare Email 1. Set environment variables: ```text \[.env] CLOUDFLARE_ACCOUNT_ID="your-account-id" CLOUDFLARE_EMAIL_API_TOKEN="your-api-token" ``` - `CLOUDFLARE_ACCOUNT_ID`: Found in your Cloudflare dashboard URL or sidebar. - `CLOUDFLARE_EMAIL_API_TOKEN`: Created in **My Profile > API Tokens** (must have "Send Email" permission). 2. Onboard your domain in the Cloudflare dashboard: **Email Sending** → **Onboard Domain** → **Add records**. 3. Update your config: ```ts \[shared/config.ts] email: { provider: enums.emailProvider.cloudflare, // Set email provider Cloudflare senderName: "Your Name from Which App", senderEmail: "no-reply@yourdomain.com", }, ``` ## Usage - **Send Pre-Configured Emails**:br Use templates like `forgotPassword`, `magicLink`, or `verifyEmail`. Example for a password reset email: ```server/api/sendResetEmail.ts import { sendEmail } from '~~/server/services/email/send'; await sendEmail({ to: 'someone@email.com', template: 'forgotPassword', params: { name: 'Someone', resetUrl: 'https://your-site.com/reset-password?token=abc', }, locale: 'en', }); ``` - **Available Templates**: - `forgotPassword`: For password reset emails. - `magicLink`: For passwordless login links. - `verifyEmail`: For email verification links. - `accountDeletion`: For account deletion confirmation email. - `waitlistConfirmation`: For joining the waitlist email. - `waitlistNotification`: For notify waitlist is over and app is live. - **Customize Templates**:br Modify templates in `server/services/email/templates/` and create new ones by adding to `index.ts` and creating a Vue component in `email/components/`. - **Verify Emails**:br Check sent emails in your provider's dashboard (Resend or Cloudflare). # Languages ## Tools - **[Nuxt I18n](https://i18n.nuxtjs.org)** – Locale and translation management ## Setup English (`en`) is enabled by default. To add another language: 1. **Register the new locale in `shared/config.ts`**:br This tells the app that the language exists and can be used. ```ts \[shared/config.ts] i18n: { defaultLocale: 'en', locales: [ { code: 'en', language: 'en-US', file: 'en.json', name: 'English' }, { code: 'es', language: 'es-ES', file: 'es.json', name: 'Spanish' }, // New ], } ``` 2. **Create the translation file for that locale** Every key in this file should match the keys used in your app. ```json \[locales/es.json] { "pages.home.title": "Bienvenidos a ShipAhead", "common.siteTagline": "Tu Boilerplate SaaS", "common.siteDescription": "Una solución poderosa para tu proyecto." } ``` 3. **(Optional) Configure routing and language detection in `nuxt.config.ts`** Do this if you want URL prefixes (for example `/es/...`) or automatic language switching based on the user’s browser. ```ts i18n: { strategy: 'prefix_except_default', // /es/about but / for default locale detectBrowserLanguage: { useCookie: true, cookieKey: 'shipahead_language', fallbackLocale: 'en' }, langDir: 'locales' } ``` ## Usage - **Translate text**:br Use `useI18n()` and reference your translation keys. ```vue const { t } = useI18n(); console.log(t('pages.home.title')); // "Welcome to ShipAhead" (en) // "Bienvenidos a ShipAhead" (es) ``` - **Switch languages**:br Use the built-in `LocaleToggler` component so users can change language from the UI. ```vue \[index.vue] ``` :brWhen a language is selected, the site updates immediately. - **Default behavior**:br English is pre-configured. To support another language, add it in `shared/config.ts` and create a matching JSON file in `locales/`. - **Browser detection** - If enabled, the app tries to match the user’s browser language. - If no match exists, it falls back to the default locale. - **Tip**:br Keep translation keys consistent (for example `buttons.save`, `errors.required`) so they are easier to maintain across languages. # SEO ## Tools - **[Nuxt SEO](https://nuxtseo.com)**: Manages meta tags, sitemaps, robots.txt, and structured data for better search engine visibility. ## Configuration Most SEO is ready out of the box. Change these only if you need custom settings: - `app/composables/useSeo.ts` – manages meta tags, sitemap rules, and private pages - `shared/config.ts`– basic SEO settings: ```ts \[shared/config.ts] appName: 'ShipAhead', // Your site name brandingImages: { openGraphImage: '/images/open-graph.png', // Social image (1200x630px) }, privatePaths: ['/admin/**', '/profile/**'], // Pages hidden from search engines ``` ## How It Works - Page titles and descriptions come from your locale files (e.g. `locales/en.json`). - Fallbacks if missing: - `common.siteTagline` → title - `common.siteDescription` → description - Automatically generates: - **Meta tags** - titles, descriptions, Open Graph, Twitter Cards - **Sitemap** - all public pages at `/sitemap.xml` - **Robots.txt** - control indexing - **JSON.LD** - structured data for Google rich snippets ## Usage - **Automatic SEO for Pages**: Add titles and descriptions in locale files: ```locales/en.json { "pages.about.title": "About ShipAhead", "pages.about.description": "Learn more about our SaaS boilerplate.", "common.siteTagline": "Default Site Tagline", "common.siteDescription": "Default Site Description" } ``` - For `/about`, use pages.about.title and pages.about.description - Multi-language ready: add to es.json, fr.json, etc. - **Manual SEO Override**: For blogs or custom pages, use `setSeo`: ```pages/blogs/ \[slug] .vue const { setSeo } = useSeo(); const blog = // fetch blog data... setSeo({ pageTitle: blog.title, pageDescription: blog.excerpt, image: blog.imageUrl // Optional: Social sharing image }); ``` - Works with multi-language pages too - Lets you control exactly what Google and social platforms show # Blogs ## Tools - **[Nuxt Content](https://content.nuxt.com/)**: Render blog posts. ## Setup 1. **Create a markdown file**: - Go to `content/blog` and add a new markdown file - For other languages: - Define a new collection in `content.config.ts` with the appropriate `source` for that locale. - Create a folder for the locale (e.g., `content/es/blog`) and add a Markdown file inside it. 2. **Markdown Content**: ```md content/blog/my-new-post.md or content/blog/en/my-new-post.md --- title: My New Blog Post description: A guide to blogging in Your App. authors: - name: Tom Han to: https://x.com/tomhan245 avatar: src: https://cdn.shipahe.ad/tomhan.webp date: 2025-09-08 badge: label: SaaS --- ## Introduction This is the content of your blog post. ``` 3. **View and Verify the Blog**: - Go to `/blog` to see the blog list with titles, descriptions, thumbnails, and categories. - Open your new post at `/blog/my-new-post` to confirm it renders correctly. 4. **SEO & Sitemap**: - SEO is handled automatically using your content's `title` and `description`. - Sitemap generation is also automatic. - Customize further in page components if needed (see [Nuxt SEO Documentation](https://nuxtseo.com)). - Track SEO and sitemap performance in [Google Search Console](https://search.google.com/search-console). ## Folder Structure ```text content/ ├─ blog/ │ └─ my-first-blog.md └─ es/ └─ blog/ └─ my-first-blog.md ``` # Documentation ## Tools - **[Nuxt Content](https://content.nuxt.com/)**: Render documentation content. ## Setup 1. **Create a markdown file**: - Add a new Markdown file under content/docs for your default language. - For other languages: - Define a new collection in `content.config.ts` with the appropriate `source` for that locale. - Create a folder for the locale (e.g., `content/es/docs`) and add a Markdown file inside it. 2. **Markdown Content**: ```md content/docs/new-doc.md or content/docs/en/new-doc.md --- title: My New Documentation description: Step-by-step guide for this document. --- ## Introduction This is the content of your document. ``` 3. **View and Verify the Document**: - Go to `/docs` to see the blog list with titles, descriptions, thumbnails, and categories. - Open your new document at `/docs/my-new-doc` to confirm it renders correctly. ## Folder Structure ```text content/ ├─ docs/ │ ├─ 1.get-started/ │ │ ├─ .navigation.yml │ │ └─ 1.index.md │ └─ 2.essentials/ │ ├─ .navigation.yml │ └─ 1.markdown-syntax.md └─ es/ └─ docs/ ├─ 1.get-started/ │ ├─ .navigation.yml │ └─ 1.index.md └─ 2.essentials/ ├─ .navigation.yml └─ 1.markdown-syntax.md ``` # Cron Jobs ## Tools - **[cron-job.org](https://cron-job.org/en/)**: External service to schedule jobs by calling your API endpoints. ## Setup & Run Cron Jobs 1. **Set CRON\_SECRET** - Add an environment variable to secure your cron endpoints: ```text \[.env] CRON_SECRET="your-secret-key" ``` - Use any strong key you like or generate one with a password generator. 2. **Add a Cron Job** - Create a file in `/server/jobs/`, e.g., `sendReminderEmails.ts`: ```text \[server/jobs/sendReminderEmails.ts] export async function sendReminderEmails() { console.log('[CRON] Running job...'); // Add your logic (DB updates, notifications, etc.) } ``` - Register it in `server/jobs/list.ts`: ```text \[server/jobs/list.ts] import { sendReminderEmails } from './sendReminderEmails'; const JOBS: any = { sendReminderEmails }; export function getJobModules(name: string) { return JOBS[name] ?? null; } ``` 3. **Schedule the Job** - Trigger your job via the API endpoint: ```text https://your-site.com/api/cron/sendReminderEmails ``` - Create a cron-job.org task: - **URL**: same as above - **Execution schedule**: e.g., `0 8 * * *` (runs daily at 8 AM) - **HTTP Header**: ```text X-Cron-Secret: your-secret-key ``` 4. **Verify** - Check server logs for `[CRON]` messages. - Or test endpoint directly with curl: ```bash curl -H "X-Cron-Secret: your-secret-key" https://your-site.com/api/cron/sendReminderEmails ``` ## Why Use cron-job.org? - No need to install `node-cron` or run background workers. - Works with **serverless platforms** like Vercel, Netlify, or Cloudflare. - Secure with your custom `X-Cron-Secret`. - Easy to schedule and manage without touching your app’s main code. ## Example: Adding a New Job - Just create a new file in `/server/jobs/`, register it in `list.ts`, and schedule it on cron-job.org like above. - You can add unlimited jobs following the same pattern. # Error Handling ShipAhead uses a custom error page (`app/error.vue`) to display clear, user-friendly messages for errors such as: - Page not found (404) - Server error (500) The page shows the error code and a **“Back to Home”** button for easy navigation. # Analytics ## Tools - [Google Analytics](https://analytics.google.com) - [Umami](https://umami.is) - [DataFast](https://datafa.st) ## Setup ### Google Analytics 1. Sign up at [Google Analytics](https://analytics.google.com). 2. Create a new property, select "Web," and follow the setup wizard. 3. Copy the **Measurement ID** (e.g., `G-XXXXXXXXXX`) from the "Data Stream" settings. 4. Set environment variable: ```text \[.env] ANALYTICS_GA_ID="your-measurement-id" ``` 5. Enable in config: ```ts \[shared/config.ts] analytics: { enableGoogleAnalytics: true, }, ``` ### Umami 1. Sign up at [Umami](https://umami.is) or self-host. 2. Add a website in the Umami dashboard. 3. Copy the **Website ID** from the tracking code. 4. Set environment variable: ```text \[.env] ANALYTICS_UMAMI_WEBSITE_ID="your-umami-website-id" ``` 5. Enable in config: ```ts \[shared/config.ts] analytics: { enableUmamiAnalytics: true, }, ``` ### DataFast 1. Sign up at [DataFast](https://datafa.st). 2. Register your site in the dashboard. 3. Copy the **Website ID** from the site configuration. 4. Set environment variable: ```text \[.env] ANALYTICS_DATAFAST_WEBSITE_ID="your-datafast-website-id" ``` 5. Enable in config: ```ts \[shared/config.ts] analytics: { enableDatafastAnalytics: true, }, ``` ## Usage - **Page Views**: Automatically tracked for every visit. - **User Actions**: Clicks, navigation, and interactions are tracked. - **Dashboard**: Check analytics data in the provider dashboards: - [Google Analytics](https://analytics.google.com) - [Umami](https://umami.is) - [DataFast](https://datafa.st) ## Track Custom Events You can track specific actions with `$trackEvent`: ```text [vue] const { $trackEvent } = useNuxtApp(); // Example: tracking a navbar button click $trackEvent('navbar', { buttonName: 'Get ShipAhead' }); ``` # PWA ## Tools - **[Vite PWA](https://vite-pwa-org.netlify.app/frameworks/nuxt.html)**: Enables app installation, caching, and push notifications for Nuxt apps. ## Setup 1. Enable in config: ```ts \[shared/config.ts] pwa: { enable: true, }, ``` 2. Replace PWA icons in `/public/images/`with your own (recommended sizes): - `pwa-icon-48x48.png` (48x48 pixels) - `pwa-icon-192x192.png` (192x192 pixels) - `pwa-icon-512x512.png` (512x512 pixels) ## Usage - Generates a web app manifest for installing the app on devices. - Caches assets for faster load times. - Test: open site in Chrome → look for install prompt. - Install the app and verify it launches like a native app. # Customer Support ## Tools - **[Crisp](https://crisp.chat/en/)**: Live chat and ticketing for real-time user support. ## Setup ### Crisp 1. Create a Crisp Account: - Sign up at [Crisp](https://crisp.chat/en/). - Create a new website in your Crisp dashboard. - Copy the `CRISP_WEBSITE_ID` from the **Integrations** menu under the **HTML** option. 2. Set environment variable: ```text \[.env] CUSTOMER_SUPPORT_ID="YOUR_CRISP_WEBSITE_ID" ``` 3. Enable in config: ```ts \[shared/config.ts] customerSupport: { enable: true, }, ``` ## Usage - **Open chat widget** – the Crisp chat appears on your site once enabled. - **Respond to users** – reply to messages from the Crisp dashboard. - **Manage tickets** – track conversations and support requests in Crisp. # Project Structure - **`app/`**: Core application logic. - `app.vue`: Main app component, defining the root layout. - `app.config.ts`: Global app configuration, including colors and Nuxt UI component classes used across the project. - `components/`: Reusable Vue components (e.g., buttons, modals). - `composables/`: Reusable logic functions (e.g., `useSeo.ts` for SEO). - `middleware/`: Route-specific middleware (e.g., authentication checks). - `pages/`: Defines routes using file-based routing (e.g., `app/pages/about.vue` creates `/about`). - `plugins/`: Nuxt plugins for extended functionality (e.g., analytics). - `error.vue`: Custom error page, any unexpected error will go to this page. - **`layouts/`**: Custom layouts for pages (e.g., `layouts/default.vue`). - **`server/`**: API routes and middleware for server-side logic. - **`public/`**: Static assets like images, favicon, or fonts (e.g., `public/images/logo.png`). - **`shared/`**: Shared configuration files (e.g., `shared/config.ts` for app settings). - **`locales/`**: Language files for internationalization (e.g., `locales/en.json`). - **`content/`**: Markdown or CMS content used by Nuxt Content (e.g., blog posts, docs). ## Usage - **Navigate the Project**: Use the folder structure to locate files for customization (e.g., edit `app/pages/index.vue` for the homepage). - **Add Pages**: Create new `.vue` files in `app/pages/` to add routes (e.g., `app/pages/contact.vue` for `/contact`). - **Customize Components**: Modify or add components in `components/` for reusable UI elements. - **Configure Settings**: Update `shared/config.ts` for app-wide settings like SEO or branding. # Page Routes ## Setup Nuxt automatically generates routes from files in the `app/pages/` directory. You only need to customize routing when using `definePageMeta`. 1. **Add a page** - Create a `.vue` file in `app/pages/` (example: `app/pages/about.vue` creates `/about`). ```text \[app/pages/about.vue] ``` 2. **Dynamic Routes**: - Use square brackets for parameters (e.g., `app/pages/blogs/[slug].vue` creates `/blogs/my-post`). - Example: ```text \[app/pages/blogs/\[slug\\].vue] ``` 3. **Nested Routes**: - Use folders with `index.vue` (example: `app/pages/dashboard/index.vue` creates `/dashboard`). - Add child routes in the same folder (example: `app/pages/dashboard/settings.vue `→ `/dashboard/settings`). ## Usage - **Basic Routing**: Add `.vue` files to `app/pages/` to create pages automatically. - **Customizing Pages**: Use `definePageMeta` to set a layout or middleware: ```text \[app/pages/admin/index.vue] definePageMeta({ layout: 'admin', requireAuth: true, }); ``` - `layout: 'admin'`: Applies the admin layout from `layouts/admin.vue`. - `requireAuth: true`: Restricts access to authenticated users, defined in ShipAhead’s middleware. - **Dynamic Parameters**: Access values like `slug` using `useRoute()`. - **Verify Routes**: Run `npm run dev` and navigating to URL (e.g., `http://localhost:3000/about`). - **Learn More**: See Nuxt routing docs at [Nuxt Pages Documentation](https://nuxt.com/docs/guide/directory-structure/pages). # API Calls ## Setup 1. **Configure Database**: Set up your database first by following the [Database Setup Guide](https://shipahe.ad/docs/features/database). 2. **Verify useApi**: The `useApi` composable is pre-configured at `app/composables/useApi.ts`. No additional setup is needed unless adding custom API endpoints. ## Usage Use the `useApi` composable in your Nuxt components to call server APIs. Below are front-end and back-end examples: 1. **Front-End Example**: Import `useApi` and call `getAdminUserStats` with error handling and loading state: ```text \[pages/admin/stats.vue] ``` :brThis fetches admin stats, shows a loading state, and displays a toast notification (pop-up message) on error. 2. **Back-End Example**: Define a server API to handle the `getAdminUserStats` request with authentication: ```text \[server/api/admin/stats.ts] import { apiSuccess } from '~~/server/utils/apiResponse'; import { requireAuth } from '~~/server/auth'; import { getUserStats } from '~~/server/services/admin/stats'; export default defineEventHandler(async (event) => { const user = await requireAuth(event); if (user.role !== 'admin') { throw createError({ statusCode: 403, statusMessage: 'Forbidden' }); } const stats = await getUserStats(); return apiSuccess(stats); }); ``` :brThis checks if the user is an admin, fetches stats, and returns a formatted response. ## How It Works - **Client-Side**: The `useApi` composable (`app/composables/useApi.ts`) uses `$fetch` to call server APIs, handling methods like GET, POST, PUT, and DELETE. - **Server-Side**: APIs in `server/api/` (e.g., `admin/stats.ts`) use services (e.g., `server/services/admin/stats.ts`) for logic and return formatted responses with `apiSuccess`. - **Error Handling**: `useApi` returns errors for invalid requests (e.g., 403 for non-admins). Front-end code can handle errors with `try/catch` and show toast notifications. - **Authentication**: Protected APIs (e.g., admin stats) require a valid user session and role, checked via `requireAuth`. - **Database Dependency**: APIs like `getAdminUserStats` require a configured database to fetch data. # State Management ## Tools - **useSharedState**: A lightweight wrapper around Vue reactivity that lets multiple pages and components share the same state. ## Setup No extra setup is needed. Call `useSharedState()` anywhere in your components. 1. **Create shared state**: ```text \[vue] ``` 2. **Update values**: ```text \[vue] ``` 3. **Use it in your page**: ```text \[vue] ``` ## How to use - The same `sharedState` is shared across all pages and components - If one page updates it, every other page sees the change - Great for: - Loading states - User/session info - Data you don’t want to refetch on every page ### Quick way to confirm it works Open two pages in your app. Update sharedState on one page - the other page will update instantly. --- Think of `useSharedState` like a **shared notebook**: When one page writes something in it, every other page can read it right away. # Legal Pages by GPT ## Setup ### Option 1: Use the Built-in Generator (Recommended) Visit: [/privacy-policy-generator](https://shipahe.ad/privacy-policy-generator) Fill in your company details and generate a GDPR & CCPA compliant Privacy Policy instantly. You can copy or export the generated content into: - `app/pages/legal/tos.vue` - `app/pages/legal/privacy-policy.vue` ### Option 2: Manual GPT Prompt Method 1. Locate the legal page files: - `app/pages/legal/tos.vue` - `app/pages/legal/privacy-policy.vue` 2. Copy the pre-written prompt from the file. 3. Paste it into GPT. 4. Copy the generated content and update the respective files. # Overview ### Tools - **[Nuxt ESLint](https://eslint.nuxt.com)**: Checks your code for errors and enforces Nuxt/Vue standards. - **[Prettier](https://prettier.io/)**: Automatically formats your code for a consistent look. - **[simple-git-hooks](https://github.com/toplenboren/simple-git-hooks)**: Runs formatting and linting when you save changes to your project. ### Usage - **Linting**: Run `npm run lint` to check for issues in your code. - **Auto Fix Lint Errors**: Run `npm run lint-fix` to automatically fix common problems. - **Formatting**: Run `npm run format` to style your code automatically. - **Full Cleanup**: Run `npm run format:all` to lint and format your entire codebase in one go. - **Auto-Formatting**: Code is automatically linted and formatted when you commit changes. ### Configuration Files Modify these only if you need custom settings: - `eslint.config.mjs`: Sets rules for code error checking. - `.prettierignore`: Lists files to skip during formatting. - `.prettierrc`: Defines formatting styles (e.g., tabs, quotes). - `package.json` (Git Hooks): Sets up auto-formatting when saving changes. # Deployment Overview Deploy your app with **Vercel** or **Cloudflare** and launch your SaaS in minutes, without errors. ## Pre-Commit and Deployment Checklist Complete these steps before committing or deploying: - Run `npm run lint` to detect code issues - Run `npm run format` to ensure consistent code style - Test locally with `npm run dev` to verify everything works - Confirm your `.env.local` values are correct (API keys, database, auth, etc.) - Do not commit sensitive files (e.g., `.env` / `.env.local`) - Commit with a clear and meaningful message - Push your changes to your GitHub repository - Make sure environment variables are added in your hosting platform ## Where to deploy Choose one and learn more about the deployment in these different guides: ::card-group :::card --- color: primary icon: skill-icons:vercel-light title: Vercel to: https://shipahe.ad/docs/deployment/vercel --- Learn how to deploy your app to Vercel. ::: :::card --- color: primary icon: devicon:cloudflareworkers title: Cloudflare Workers to: https://shipahe.ad/docs/deployment/cloudflare --- Learn how to deploy your app to Cloudflare Workers. ::: :: # Vercel ## Setup 1. Sign up / Log in to [Vercel](https://vercel.com) and click **New Project**. 2. Import your GitHub repository. 3. Set the **Framework Preset** to **Nuxt**. 4. Add your environment variables from `.env` if required. 5. Click **Deploy** to build and publish your app. 6. Open and verify your live app using the generated Vercel URL. 7. Auto-deploy happens on every push to the main branch. 8. Check logs in Vercel if something fails during build or runtime. # Cloudflare Workers ## Setup 1. Sign up / Log in to Cloudflare. 2. Set up Hyperdrive (for database connections): - In the Cloudflare dashboard, go to **Storage & Databases → Hyperdrive**. - Click **Create Hyperdrive** and connect it to your database (e.g., Postgres, MySQL). - Once created, copy the **Hyperdrive ID**. - Run the following command in your project ```text \[Terminal] mv wrangler.example.toml wrangler.toml ``` - Set it to wrangler.toml: ```text \[wrangler.toml] [[hyperdrive]] binding = "HYPERDRIVE" id = "your-hyperdrive-id" ``` 3. Set nitro preset in environment variable: ```text \[.env] NITRO_PRESET="cloudflare_module" ``` 4. Commit changes and push to your repository. 5. Deploy via Cloudflare: - Go to **Workers & Pages → Create Application → Create Worker**. - Connect your GitHub repository. - Set the build command to: `npm run build` - Add environment variables (`.env.local` values). - Click Deploy to build and launch 6. Access and verify your live site at the Cloudflare Workers URL. 7. Auto-deploy happens on every push to the main branch. 8. Check logs in Cloudflare dashboard if something fails during build or runtime. # 7 Nuxt CI/CD tools with a battle-tested release checklist ![Ship Nuxt reliably with a CI/CD stack we use in production. Tools, example configs, and a practical release checklist for a typed Nuxt SaaS codebase.](https://shipahe.ad/images/blog/7-nuxt-ci-cd-tools-and-a-checklist-for-reliable-releases/post-411.webp){style="max-width:100%;border-radius:12px"} Shipping a Nuxt app every week without pager noise is a process problem, not a framework problem. This is the CI/CD stack and checklist we use to ship our typed Nuxt SaaS starter, Shipahe.ad, on a tight loop. It keeps builds fast, previews useful, and releases boring in the best way. ## 1. Start with a CI-friendly Nuxt starter A pipeline is only as stable as the codebase it validates. A fully typed Nuxt starter like Shipahe.ad gives CI clear targets to check: database and ORM with migrations, authentication, protected routes, an admin panel, transactional emails, payments with webhooks, S3-compatible storage, i18n, analytics, SEO helpers, cron jobs, and a landing page. Those pieces map to automated steps instead of hand-written one-offs. Because the code is typed end to end, a TypeScript check in CI catches whole classes of bugs before they hit a preview. We also design our repo with CI in mind: consistent scripts in package.json, conventional commits for readable changelogs, test fixtures for auth and billing, seed data for admin flows, and a minimal .env.example for each environment. That structure makes it simple to wire jobs and safe to onboard AI coding tools like Cursor or Claude to generate pipeline changes without breaking guardrails. ## 2. Runners and caching: make builds fast and repeatable Pick a runner that mirrors where you deploy. GitHub Actions, GitLab CI, and CircleCI are flexible and work well when you deploy to SSH targets or container platforms. If you deploy to Vercel, Netlify, or Cloudflare Pages, their native pipelines give you atomic deploys and solid previews. Use a self-hosted runner only when you need custom system packages or private networking to reach internal databases. Caching is the cheapest speed win. Cache your package manager store and the build output with keys that change only when inputs change. For Node projects we standardize on pnpm and cache against OS, Node version, and lockfile: ``` ``` For monorepos, split caches per workspace so a docs change does not bust app caches. If your host can reuse artifacts, publish the .nuxt output from CI and have deploy jobs pull it instead of rebuilding. ## 3. Make quality gates non-negotiable Gate merges on checks that reflect real user risk. We keep four lanes: - Lint and formatting: run ESLint and your formatter before anything else. Fail fast on unused exports and accidental console logs. - Type safety: run `pnpm typecheck` and treat new errors as blockers. On a typed starter like Shipahe.ad, this pays off immediately. - Unit and component tests: run in parallel with the build. Keep them deterministic with seed data and factory helpers. - Smoke-level E2E: headless Playwright is enough. Cover home, sign in, a protected page, an admin action, and one payment flow in test mode. Use a matrix when needed, but do not overspend. If production runs Node 20 on Linux, that is the lane that matters. Add branch protection so main stays deployable. Use `concurrency` to cancel in-progress jobs on rapid pushes and keep the queue clear. ## 4. Previews and environment management Every pull request should produce a preview you can click. Reviewers catch more by clicking than by reading diffs, especially for auth-gated and i18n features. Previews are only useful if they are safe and complete: - Seeded auth: provision a test user and admin in your seed script. In Nuxt, wire a CLI task like `pnpm db:seed` into the preview job. - Payments in test mode: use provider test keys and static webhook secrets for previews. Hit a health endpoint that confirms webhooks return 2xx. - Ephemeral data: point previews at an isolated database. Auto-create the schema, run migrations, and drop it on cleanup. - i18n sanity: toggle the locale switcher in E2E and confirm translated routes and SEO tags render. Manage secrets as pipeline inputs, not as .env files in the repo. In Actions or your CI of choice, scope secrets to environments and jobs. For Nuxt 3, use runtimeConfig to separate public and server values. A typical mapping looks like this: ``` ``` Keep production-only features behind flags. In Nuxt, read flags from runtimeConfig and guard routes and components. This prevents private beta features from leaking in previews or to the public site. ## 5. Plan rollouts, monitor, and communicate Small, frequent releases reduce risk. Use atomic or immutable deploys when your host supports them so rollbacks are a click, not a rebuild. For higher-risk changes, do a staged rollout: route a small percent of traffic to the new build or enable a feature flag for a cohort. Monitoring starts in CI. Fail the deploy if database migrations do not apply in staging. In production, watch error rates, webhook failures, and checkout conversion in the first hour after a release. Keep a one-command rollback documented in the repo that also handles database considerations. We keep the previous build artifact and a down migration ready for tagged releases. Write release notes that map to user value, not just technical changes. If a change affects public pages or docs, coordinate with your content workflow. For teams that care about search and how AI answers surface your updates, this is a useful read: [this SEO automation tool guide to generative engine optimization (GEO)](https://rankgoat.app/blog/what-is-generative-engine-optimization-geo-plain-english-guide){rel=""dofollow""}. It explains how automated content, technical fixes, and backlinks influence both Google rankings and AI answer boxes. ### A pre-flight checklist for reliable Nuxt releases - Build sanity: Node version pinned, dependency cache restored, build completed without warnings you plan to ignore. - Type safety: TypeScript check passes. For typed starters like Shipahe.ad, treat any new type error as a blocker. - Auth and protected pages: Login, magic link, Google sign-in, and logout flows verified in preview. Protected routes only load for authenticated users. - Admin panel: Admin dashboard loads, user management actions work, spam ban action tested with a dummy account. - Payments: One-time checkout and subscription flow tested in provider test mode. Webhooks reachable and returning 2xx. No live keys in non-production. - Emails: Password reset, welcome, and notification templates render with real data in a staging inbox. Links point to the right environment. - Database and ORM: Pending migrations applied in staging, rollback path documented. Seed scripts safe to re-run. - File uploads: S3-compatible storage keys present, test upload and secure download work. Old artifacts clean up on rollback. - i18n: Language switch works, translated routes render, and SEO tags exist for each locale where relevant. - Cron jobs: Scheduled tasks enabled in production only. Daily reports and reminders point to production services. - Analytics: Built-in analytics receiving pageviews and signups in staging and production with separate datasets. Sampling and privacy settings reviewed. - SEO: Automatic meta tags and Open Graph images render in preview. Sitemap generated and accessible. Changelog or release notes drafted for user-facing changes. - Access control: Feature flags or environment checks in place so experimental features do not leak to all users. - Rollback: Previous build still available. One command or click documented to revert, including database considerations. ### Key takeaways - Pick a runner that fits your host and security needs, then cache everything you can. - Automate linting, type checks, unit tests, and a small set of E2E smokes so main is always releasable. - Use preview deployments to validate UI, auth, payments, and i18n before merging. - Treat secrets, webhooks, and cron jobs as part of the release, not afterthoughts. - Prefer atomic deploys, keep a clear rollback, and publish notes users can trust. CI/CD is not a trophy pipeline. It is a habit. Start small, script the boring parts, and keep shipping. If you prefer to start from a Nuxt SaaS boilerplate you can buy, choose one like Shipahe.ad that already includes authentication, payments, emails, analytics, SEO tools, i18n, cron jobs, and an admin. Your pipeline then maps to real features on day one. ## Recommended resources - [this SEO automation tool guide to generative engine optimization (GEO)](https://rankgoat.app) # Nuxt Boilerplate for SaaS: What to Ship First and Why ![Use a Nuxt boilerplate to launch a SaaS fast. See the core pieces, build vs buy, a 10 day plan, and how Shipahe.ad handles auth, payments, i18n, admin, and SEO.](https://shipahe.ad/images/blog/beginners-guide-nuxt-boilerplate-saas-apps/post-513.webp){style="max-width:100%;border-radius:12px"} You do not get paid for wiring login flows, checkout, and settings. You get paid for solving a customer problem. A Nuxt boilerplate gives you a working base so you can ship the money path first and get real users in days, not months. Below is a practical take on what a Nuxt boilerplate is, the parts a SaaS actually needs, when to build vs buy, and a 10 day plan to reach a usable, payworthy first release. ## Ship faster with a Nuxt boilerplate Nuxt sits on top of Vue and gives you file based routing, server rendered pages, and a clean conventions over configuration setup. You organize pages in `/pages`, server endpoints in `/server/api`, and guard routes with middleware. SSR and API routes run on Nitro, which keeps the same code working locally and in production. A Nuxt boilerplate is a repo that turns those primitives into a ready to run app: auth flows, protected pages, checkout, admin, and the basic marketing surface. It removes weeks of glue work so you can put most of your time into one or two core features that prove value. With Shipahe.ad, that foundation is prebuilt: user authentication with email, magic links, and Google, protected routes, checkout for one time and subscriptions with swappable providers, a typed database with an ORM and migrations, S3 compatible file uploads, transactional emails, an admin panel, built in analytics, SEO helpers, scheduled jobs, AI chat and generation with switchable GPT models, a blog, and a customizable landing page. It is also tuned to play well with AI coding tools like Cursor and Claude if you use them in your workflow. ## The building blocks your SaaS actually needs ### Accounts and protected areas Users should be able to sign up, sign in, and reach private pages without friction. A solid boilerplate ships email and password, magic links, and a social provider like Google. Route middleware keeps private pages off limits to guests. Plan for password resets and session revocation from day one. ### Payments and plans Revenue depends on a checkout that works every time. You want a drop in flow for subscriptions and one time payments, trials, upgrades, downgrades, cancellations, and invoices. Webhook handling with signature verification and idempotency is non negotiable. Proration rules and trial transitions are easy to get wrong, so start with tested flows and adapt pricing, not the protocol. ### Data, files, and email Your app needs migrations, typed models, and a repeatable seed script. For uploads, prefer presigned URLs to avoid proxying large files through your server. Transactional email templates for welcome, password reset, and purchase receipts should be ready to edit. Use environment specific SMTP keys and verify domains early to avoid deliverability surprises later. ### Admin and analytics You will want to see users, plans, and events at a glance. An admin panel that lists accounts, flags spam, and lets you ban abusers saves hours. Lightweight analytics for pageviews, signups, and conversion let you find leaks without adding another tool on day one. Log key events to your admin for fast debugging. ### i18n and SEO Internationalization only works if it is part of the skeleton. A language switcher, locale files, and per locale routes make translation straightforward. On the SEO side, generate meta tags, Open Graph, and a sitemap by default so marketing pages index correctly and look right when shared. ### Automation and scheduled jobs Many SaaS workflows are time based. A scheduler for daily digests, usage resets, reminder emails, or cleanup tasks keeps you from bolting on cron later. Local development should let you run and test these jobs by hand. ### AI features and developer workflow If you are building an AI product, start with working chat, text, and image generation endpoints and usage limits. Keep model providers swappable so cost and latency experiments are cheap. Make sure the dev loop is short: type safe APIs, hot module reload, and scripts for seeding, running tests, and pushing to staging. ### Marketing surface Launch with a customizable landing page and a blog. Nuxt Content with Markdown is enough to publish updates and rank for early terms. Wire CTAs to your signup and set canonical URLs, social images, and schema. ## Build vs buy: a practical call Building everything yourself is possible, but it costs calendar time and attention you will not get back. The risky parts are not glamorous: OAuth callback edge cases, webhook retries and replay protection, subscription proration, VAT and tax settings, presigned upload security, and email deliverability. Each one can burn a week. - If your app needs a highly unusual auth flow or a novel billing model, you may need custom work. Budget the time. - If your needs are typical, start with a Nuxt boilerplate and adapt it. You keep control of your product while skipping unoriginal scaffolding. - Consistency matters. A starter with conventions, typed models, tests, and scripts reduces regressions when you iterate. The goal is not to outsource judgment. It is to remove low level plumbing so you can spend your best hours on the feature that gets someone to pay. ## A 10 day launch plan with a starter kit 1. **Day 1: run the app and secure routes.** Install, boot locally, create an account, and hit a protected page. Add a logged out route test and a logged in route test to catch regressions. 2. **Day 2: wire payments end to end.** Configure keys, create a test product and price, and run both a one time and a subscription checkout in test mode. Verify webhooks, idempotency keys, and error handling. Cancel, upgrade, and downgrade once to see proration behavior. 3. **Day 3: brand the surface.** Replace logo, colors, and typography on the landing page. Update copy blocks, FAQs, and CTAs. Set meta tags, Open Graph images, and a sitemap. Publish a first blog post that outlines the problem you solve and links to signup. 4. **Day 4: i18n baseline.** Turn on the language switch. Translate the landing page and one core screen into a second language to validate your translation workflow and routing. Store the user’s locale preference. 5. **Day 5: emails that earn trust.** Edit welcome, password reset, and receipt templates. Send test emails to real inboxes, check spam folders, and set SPF, DKIM, and DMARC. Add a footer with support links and your company details. 6. **Day 6: data and uploads.** Define the first two domain models, write migrations, and seed sample data. Configure S3 compatible storage and test presigned uploads and secure downloads from a protected page. 7. **Day 7: admin and analytics.** Add filters to the user list, a plan column, and a ban flow. Confirm that pageview and signup events show up. Log key events such as checkout completed, plan changed, and email sent so you can debug quickly. 8. **Day 8: feedback loop.** Invite a few testers. Capture qualitative input where it is easy to process. If you need structure, set up [product feedback management with Feedjolt](https://feedjolt.com) so customers can submit, vote, and you can merge duplicates and prioritize in public. Integrate Slack or issue tracking if that helps you act fast. 9. **Day 9: AI feature slice.** If you are building an AI tool, ship a thin vertical slice: one prompt, one route, usage limits, and a simple history view. Start with a default model and keep the provider swappable so you can test cost and speed later. 10. **Day 10: staging and release.** Create separate environments for local, staging, and production. Lock down env vars, rotate keys, and run smoke tests: signup, login, checkout, receipt, i18n toggle, and a protected page. Ship to production and invite the first paying users. From here, add tests around the money path, monitor failures in your admin, and iterate on the one feature that keeps people coming back. ## Key takeaways - A Nuxt boilerplate removes weeks of glue work so you can ship the money path first. - The essentials are auth, payments, data and files, emails, admin, analytics, i18n, SEO, automation, AI endpoints if needed, and a marketing surface. - Use a starter when your needs are typical and focus on your product’s core value. Build custom only where you must. - Shipahe.ad bundles the pieces most teams build anyway and lets you start at feature one. - Do less but finish: signup, checkout, one protected page, and one core feature live in 10 days is a realistic goal. A starter kit does not decide your product, but it clears the path. Pick a boilerplate that matches your needs, verify the critical flows, and put version one in front of real users this week. ## Recommended resources - [product feedback management with Feedjolt](https://feedjolt.com) # Best Nuxt admin templates for SaaS dashboards in 2026 A SaaS dashboard has to look polished, feel fast, and stay flexible as your product grows. Pick the wrong Nuxt admin template and you will spend weeks undoing opinions. Pick the right one and you can move from a Figma mock to a working, branded dashboard in days. This guide focuses on Nuxt 3 options that scale with real teams. You will see how the main template approaches compare, when a full starter kit makes more sense, what to expect on pricing and support, and the setup pitfalls that cost time if you miss them. ## How we evaluated Nuxt admin options A workable template should get you to a secure, themeable, data-rich dashboard without fighting the framework. We prioritized Nuxt-first stacks and measured them by how quickly we could ship a sortable table, a chart, and protected routes. - Framework fit. Native Nuxt 3 support, SSR compatibility, route middleware for protected areas, and predictable layouts. - Component depth. Tables, forms, charts, dialogs, toasts, and navigation primitives that cover daily admin tasks. - Design system. Themeable tokens for color, spacing, and typography with dark mode and accessible states. - Developer ergonomics. TypeScript types, sane folder structure, plugin setup, and clear examples. - Performance and a11y. Reasonable bundle size, lazy loading, semantic HTML, keyboard navigation, and focus management. - Licensing and support. Transparent terms, update cadence, and evidence of maintenance or community adoption. We built a small demo with each approach, timed the path to a sortable data table and a chart, checked Lighthouse for a baseline, and verified how easily we could adapt brand tokens and add auth-guarded routes. ## The main Nuxt admin template approaches ### Tailwind-first Nuxt admin template A Tailwind-first stack gives utility-first styling, predictable spacing, and a fast path to on-brand UI. Paired with headless components, you assemble only what you need and keep CSS overhead low. - Starter sketch. Install Tailwind in Nuxt, add a layout with a sidebar and top bar, wire dark mode with a color-mode module or a simple class toggle, and compose cards, tables, and forms from headless primitives. For charts, mount a client-only component to avoid SSR pitfalls. - Pros. Lightweight, easy to theme via tokens, integrates cleanly with Nuxt file-based routing and layouts, and is straightforward to performance-tune. - Cons. More assembly work for data-heavy widgets, and accessibility depends on the headless primitives and how you wire them. - Best for. Teams that value performance, brand control, and clean code. Great for early SaaS dashboards that will evolve quickly. ### Vuetify-based Nuxt admin template Vuetify delivers a mature Material Design system with consistent patterns out of the box. It reduces decision fatigue and accelerates dense admin screens. - Starter sketch. Install Vuetify 3, register it in a Nuxt plugin, include the styles, and use built-in layouts, navigation drawers, data tables, and form controls. Prefer server-side pagination and sorting on large tables to keep interactions snappy. - Pros. Deep component suite, sensible defaults, robust accessibility, and strong documentation for complex layouts. - Cons. Heavier bundle footprint and a Material look that takes work to fully restyle. - Best for. B2B products that want predictable UX and reliable building blocks over minimal bundle size. ### PrimeVue-based Nuxt admin template PrimeVue shines when you need advanced data components like powerful tables, trees, and filters. It is a quick route to CRUD-heavy dashboards and reporting views. - Starter sketch. Install PrimeVue and PrimeIcons, import a theme CSS in nuxt.config, register a plugin, and drop in DataTable, Dropdown, Calendar, and OverlayPanel components. Use lazy loading for tables and virtual scrolling where datasets are large. - Pros. Wide component coverage, multiple theming options, fast path to complex inputs and data navigation. - Cons. Configuration-heavy components have a learning curve, and visual style can clash if mixed with other systems. - Best for. Data-dense SaaS where the admin doubles as a light analytics or reporting surface. ### Minimal Nuxt admin shell with Composition API Sometimes the best template is a thin, predictable shell. With Nuxt layouts and the Composition API, you can stand up a secure, type-safe admin in an afternoon. - Starter sketch. Create an admin layout with a sidebar and top bar, add route middleware for auth, define a base card and table, and integrate your preferred chart and form libraries. Use a typed store for user and permissions. - Pros. Small surface area, zero lock-in, and easy to optimize. Clean mental model for senior teams. - Cons. You build most widgets yourself, which takes time for complex screens. - Best for. Experienced developers or teams with a strong in-house design system and strict brand requirements. ## Full Nuxt SaaS starter kit: Shipahe.ad When you need more than UI, a full Nuxt starter kit saves months. Shipahe.ad is a Nuxt boilerplate with an Admin Panel and a prebuilt landing page you can customize, so you launch dashboards and customer pages fast and start charging sooner. - Admin Panel. View users, manage accounts, and ban spammers with role-based controls. - User authentication. Email and password, magic links, social logins, password reset, and protected pages wired end to end. - Payments. One-time and subscription flows with customer portal patterns ready to adapt to your provider. - Internationalization. Multi-language support with an in-app language switch and translation keys organized for scale. - Transactional email. Pre-made templates for resets, welcomes, and notifications with a clean abstraction for providers. - Database. Preconfigured ORM and migrations in a fully typed codebase, including seed scripts for local dev. - File storage. S3-compatible uploads with signed access for secure delivery. - AI features. Chat, text, and image generation with switchable GPT-style models, plus hooks for AI coding tools. - Operational tooling. Built-in analytics, SEO helpers, cron jobs, and a Nuxt Content blog. - Marketing. A prebuilt, editable landing page that ships on day one. Who benefits most. Founders and small teams that want to skip wiring auth, payments, i18n, emails, analytics, and admin again. If your goal is to build and sell an AI tool or SaaS quickly, Shipahe.ad gives you the rails to move from idea to revenue without reimplementing the same infrastructure. ## Pricing, licensing, and support Templates range from free MIT stacks to commercial licenses with updates. Free lowers cost but shifts maintenance to you. Commercial licenses often include patterns and examples that compress build time and de-risk edge cases. - License scope. Check whether the license covers a single project or unlimited products. Confirm if employees and contractors are both allowed under the same seat. - Update policy. Look for clear versioning, changelogs, and migration guides. A monthly or quarterly cadence is a healthy signal. - Support expectations. Clarify whether support means docs only, an issue tracker, or email with response-time targets. Ask how long critical fixes typically take. For a Nuxt SaaS template you plan to run in production, optimize for total cost of ownership over 12 months. An option that gets you to a reliable release in weeks and stays maintainable is usually cheaper than a free template that burns time on auth, billing, and dashboards. ## Setup tips and common pitfalls - Lock framework versions. Start from the template’s recommended Nuxt and Vue versions. Minor mismatches can break SSR or devtools. - Plan auth early. Add route middleware to guard admin pages, protect server routes, and test logout flows. Do not index admin routes in robots or sitemaps. - Define design tokens first. Set colors, spacing, typography, and radii before building screens to avoid rework when brand updates land. - Tables and charts. Tree-shake chart libraries and paginate server-side. Prefer lazy components for heavy visuals to keep TTI low. - Accessibility passes. Test keyboard navigation, focus traps in dialogs, and visible focus states. Add a skip link in the layout. - i18n from day one. Use translation keys and namespaces. Avoid hardcoded copy in components. - Environment safety. Keep secrets server-side and expose only what you must via public runtime config. Never leak credentials into client bundles. - Error states. Design empty, loading, and failure states for every critical view. An admin with clear fallbacks reduces support load. - Analytics and SEO. Exclude admin from pageview tracking and sitemaps. Keep marketing pages fast with image optimization and prefetching. **Key takeaways** - Choose the approach that matches your component needs and design system, not just the prettiest demo. - Tailwind-first gives speed and control, Vuetify and PrimeVue accelerate dense UIs, and a minimal shell maximizes flexibility. - Free is fine for prototypes, but commercial support can repay itself in a single week of saved time. - Plan auth, routing, and a11y up front to avoid expensive rewrites. - When you need dashboards plus auth, payments, i18n, emails, analytics, and SEO, a full Nuxt boilerplate like Shipahe.ad is faster and safer. # The Best SaaS Stack in 2026 – Tools to Build and Launch Fast I’ve wasted more time than I’d like to admit choosing a "perfect" tech stack. You know the drill: You spend three days comparing Drizzle vs Prisma, another two days wrestling with auth libraries, and by the time you're ready to write your first feature, the excitement for the project has already started to fade. In 2026, the tech landscape is noisier than ever. But if your goal is to launch a profitable SaaS (and not just play with new frameworks), you need a stack that gets out of your way. This is the exact, no-fluff architecture I use to ship fast and scale without the headache. --- ## Why Your Choice of Tools Matters Your technical choice is the foundation of your house. If the foundation is weak, the house falls down when you try to add a second floor. Choosing the right **modern SaaS development** tools helps you: - **Move Fast:** You don't build everything from scratch. - **Scale Without Stress:** Your app handles 1,000 or 100,000 users just as easily. - **Focus on Value:** You spend your time on the features that people actually pay for. Many smart founders use a **SaaS boilerplate architecture** like [ShipAhead](https://shipahe.ad){rel=""nofollow""} to skip the boring config work and get straight to building. --- ## The Front-End: Speed and SEO ### Nuxt 4 + Vue 3 Your front-end is what your users see and feel. For 2026, **Nuxt 4** is the gold standard. It is fast, handles SEO naturally, and has a great developer experience. It makes your site feel like a local app rather than a slow website. ### Tailwind CSS Design is hard. **Tailwind CSS** makes it easy. Instead of writing messy CSS files, you use simple classes to style your app. It is the fastest way to build beautiful, responsive interfaces that work perfectly on phones and computers. --- ## The Back-End: Reliability and Data ### Database: Postgres + Drizzle ORM Data is the heart of your SaaS. **Postgres** is the most reliable database choice. It is safe, fast, and works everywhere. Pair it with **Drizzle ORM** to talk to your database. Drizzle stops you from making common mistakes and keeps your code clean. ### Node.js + Serverless You don't want to manage servers. Using **serverless** functions means you only pay for what you use. If nobody is on your site, you pay zero. When you go viral, your backend scales up automatically. --- ## Essential Infrastructure: Login and Payments ### Better Auth for Safe Logins Security is scary. Don't build your own login system. Use **Better Auth**. It handles passwords, Google logins, and session management for you. This keeps your user data safe while giving you more time to build. ### Stripe for Payments If you want to make money, use **Stripe**. It is the industry standard for **full-stack SaaS tools**. Stripe handles monthly subscriptions, tax, and one-time payments with a few lines of code. --- ## Working with AI Coding Tools In 2026, you shouldn't be writing every line of code by hand. Tools like **Cursor** and **Claude** are essential. The secret to using AI effectively is having a clean **Nuxt 4 SaaS** structure. When your code is organized, AI can understand your project and suggest fixes in seconds. This is why a standardized stack is so powerful. --- ## Deployment: Putting Your App Online ### Vercel or Cloudflare In 2026, "deploying" should take one click. **Vercel** and **Cloudflare** are the best platforms for hosting modern apps. They handle the security, caching, and global delivery of your SaaS so you don't have to hire a DevOps engineer. --- ## ShipAhead: The Shortest Path to Launch Setting all of this up manually takes weeks. [ShipAhead](https://shipahe.ad){rel=""nofollow""} gives you a professional **scalable SaaS guide** in code. It comes with: - **Pre-built Nuxt 4 & Tailwind** setup. - **Fully integrated Authentication** with Better Auth. - **Stripe payments** ready for your API key. - **Postgres & Drizzle** database configuration. It is designed for founders who want to build a business, not just a configuration file. ### How to Choose the Best Foundation? If you are still undecided, check out our comprehensive guide on the [7+ Best Nuxt Starter Kits for 2026](https://shipahe.ad/blog/top-saas-starter-kits) where we compare the top options for rapid development. --- ## Final Thoughts The **Best SaaS Tech Stack 2026** is about choosing simplicity over complexity. By using Nuxt, Postgres, and Stripe, you are setting yourself up for success. Don't wait for the "perfect" time. Pick your tools, use a starter kit, and start shipping. The world needs your idea. # Best SaaS starter kit 2026: Nuxt, Vue, and more compared ![Find the best SaaS starter kit for 2026. We compare Nuxt, Vue, and other stacks on auth, payments, admin, i18n, SEO, analytics, AI, and time to market.](https://shipahe.ad/images/blog/best-saas-starter-kit-2026-nuxt-vue-and-more-compared/post-765.webp){style="max-width:100%;border-radius:12px"} You want to ship fast without shipping junk. A good SaaS starter kit trims weeks of setup and gives you production basics on day one: auth, subscriptions, admin, i18n, analytics, SEO, and a landing page that can take a card. This review compares Nuxt, Vue, and other stacks using the same yardsticks. I built a simple subscription app and a small AI feature with each kit, then timed the path to first payment and first model response. Below is what consistently mattered and where the kits differed. ## What to measure in a SaaS starter kit Shiny demos hide edge cases. These are the checks that separated solid starters from costly detours. - **Authentication you can trust.** Email and social sign-in, password reset, and magic links are table stakes. Look for session invalidation on password change, rate-limited auth endpoints, role-based route guards, and working “sign out everywhere.” - **Subscriptions that survive production.** Prebuilt checkout for recurring and one-time payments is not enough. You want tested webhook handlers, idempotency keys, trial handling, proration for plan changes, tax support, and a clean way to swap providers later. - **Admin that reduces support.** A usable dashboard should let you search users, view invoices or failed charges, toggle roles, ban obvious abuse, and export data. Impersonation and event timelines save hours of back-and-forth. - **Internationalization that persists.** Locale-aware routes or cookies, an in-app language switch, server-rendered translations, and a simple flow for adding languages. RTL support is a plus if you need it. - **Analytics and SEO by default.** Server-side pageview and signup tracking, basic funnels, sitemap, canonical tags, Open Graph images, and sensible meta defaults to avoid thin pages. - **Files and email that do not leak.** S3-compatible uploads with signed URLs, short-lived tokens, image resizing, and transactional emails with local previews and retry logic. - **AI readiness.** Examples for chat and generation with streaming responses, token accounting, and safe rate limits. The codebase should be typed and friendly to AI coding tools so refactors do not break runtime contracts. - **Docs and setup flow.** A seed script, fixtures, and a quickstart that moves you from clone to “first subscription” without hunting through source files. ### Quick checklist - Auth: email + magic link + social, protected routes, and session invalidation. - Payments: subscriptions, trials, proration, webhooks, tax, and provider swap path. - Admin: search, roles, moderation, and basic revenue or retention views. - i18n: visible toggle, persisted choice, and server-rendered translations. - Analytics & SEO: events, sitemap, OG images, canonical tags. - Files & email: signed URLs, image transforms, templates, and retries. - AI: chat and generation examples with streaming and limits. - DX: seed data, typed models, and a clear deployment story. ## Our Nuxt pick: Shipahe.ad Nuxt SaaS starter kit If you want a Vue/Nuxt starter that covers business basics and modern AI use cases, the Shipahe.ad Nuxt boilerplate lines up with launch needs instead of demo checkboxes. It ships with the patterns I expect to use in a real product and stays close to Nuxt conventions so you can extend it without fighting abstractions. ### Pros - **Authentication options.** Email and password, magic links, Google sign-in, password reset, and protected pages with server and client guards. - **Payments and checkout.** One-time and subscription flows with webhooks, trial support, and a clean interface for swapping providers when pricing or geography changes. - **Admin panel.** A dashboard to review users, manage accounts, and ban spammers. Useful defaults instead of a blank shell. - **Multi-language support.** Built-in i18n with a language switch that persists and renders on the server. - **Transactional emails.** Templates for resets, welcomes, and notifications with local preview. - **Database and typing.** Preconfigured database with an ORM, typed models, and migrations you can understand and edit. - **File storage.** S3-compatible uploads with signed access patterns ready to drop into forms. - **AI chat and generation.** Working chat, text, and image examples with switchable models and streaming responses. Plays well with AI coding tools like Cursor and Claude in a typed codebase. - **Analytics and SEO.** Pageview and signup tracking built in, plus automatic meta tags, Open Graph images, and sitemaps. - **Prebuilt landing page and blog.** A landing page you can brand in minutes and a Nuxt Content blog with i18n and SEO baked in. - **Cron jobs.** Scheduled tasks for reports, reminders, and cleanups. ### Cons - Opinionated Nuxt stack. React-first teams may prefer a Next.js kit. - Commercial license. Budget for it instead of stitching free pieces for weeks. - Nuxt familiarity helps. You get more out of the patterns if you know the framework. ### Who it is for Founders and teams who want a Nuxt SaaS boilerplate that includes payments, i18n, admin, analytics, SEO tools, and AI generation from day one. If you plan to build a SaaS, an AI tool, or a multi-language web app on Nuxt, this gets you to a sellable product fast. ## Alternatives by stack ### Vue/Nuxt community templates Community starters in the Vue and Nuxt ecosystem give you SSR, routing, and solid DX. Many include basic auth and a landing page, some show Stripe examples. The tradeoff is you often assemble admin, i18n, file storage, and email. Expect to wire webhooks, write guards, and decide your own folder conventions for background jobs. **Good fit:** experienced Vue developers who want control and accept doing subscriptions, emails, and admin on their own. ### Next.js and React starters Next.js has depth and plenty of examples for auth and payments. Hosting stories are polished, and you can find a starter for almost any taste. Full admin, i18n, analytics, and transactional email usually need extra work unless you pick a more opinionated commercial kit. Fragmentation across router versions and server components can add decision overhead. **Good fit:** React-standardized teams that want a head start but plan to compose services around the core. ### Laravel and Rails starters Batteries-included server frameworks make it easy to go from scaffold to revenue. Monoliths simplify deployments and background jobs, and CRUD-heavy apps fly. For modern SPA polish or AI chat UIs, you will add more front-end structure than a Nuxt-based approach, especially for streaming updates. **Good fit:** backend-first teams that value predictable patterns and can layer richer front-end and AI pieces as needed. ## Cost, ROI, and setup friction Wiring auth, subscriptions, admin, i18n, emails, analytics, SEO, file storage, and a landing page from scratch usually lands between 60 and 120 hours. A focused Nuxt SaaS template can compress that to days. Here is how the time tends to disappear when you build it yourself: - **Auth and protected pages:** 10 - 20 hours to handle flows, guards, and edge cases like token reuse and session invalidation. - **Subscriptions and webhooks:** 15 - 25 hours to implement checkout, trials, proration, retries, and idempotent handlers. - **Admin panel:** 10 - 20 hours for list, search, detail views, role toggles, and audit trails. - **i18n:** 6 - 12 hours for routing, persistence, and translation keys. - **Emails and storage:** 6 - 12 hours for templates, local preview, signed URLs, and image transforms. - **Analytics and SEO:** 6 - 10 hours for event logging, sitemap, canonical tags, and OG images. - **Landing page and blog:** 6 - 10 hours to get a credible launch site with analytics and forms. AI-native products also win by shipping earlier. For example, [the ApplyTop AI resume builder](https://applytop.com){rel=""dofollow""} shows how a clear job-to-be-done can connect AI generation to paid users. It scans LinkedIn, career sites, and ATS platforms, sends matched job alerts, and generates tailored resumes and cover letters. If you are asking how to build and sell an AI tool online, pick a starter that already includes AI chat and generation alongside subscriptions so you can test pricing in week one. The hidden cost in any starter is the first week. Good kits include a project seed, example data, and docs that move you from install to first payment without context switching. The Shipahe.ad Nuxt starter adds typed models and patterns that AI coding tools can understand, so Cursor or Claude can propose refactors without breaking runtime behavior. ## Key takeaways - Judge starters by production realities: tested auth, durable subscriptions, admin, i18n, analytics, SEO, files, and email. - If you want a Nuxt SaaS template, Shipahe.ad is a strong pick with AI chat and generation, subscriptions, and a prebuilt landing page. - Time to market compounds. A ready Vue/Nuxt starter turns months of plumbing into a week of setup and gives you more cycles for the actual product. ## FAQ ### What makes a SaaS starter kit worth paying for? It should save you weeks of setup by shipping auth, subscriptions, admin, i18n, analytics, SEO, email, and file storage that you would otherwise build yourself. ### Is a Nuxt boilerplate a good fit if my team is new to Vue? Yes if it includes clear examples and a prebuilt landing page, but expect a brief learning curve. Good docs and typed patterns help you stay productive. ### Can I launch an AI tool with a starter kit? Pick a kit with AI chat and generation examples plus subscriptions. That lets you test pricing and usage early instead of wiring everything from scratch. ### How do I compare pricing across starter kits? Estimate the hours you would spend building missing features. Even a higher-priced kit usually wins if it saves 40 to 80 hours of development. ### Do I need built-in analytics and SEO tools? Yes. Auto meta tags, OG images, sitemaps, and event tracking let you validate traction and ship content without detours. ## Recommended resources - [the ApplyTop AI resume builder](https://applytop.com) # How to Choose a Nuxt SaaS Boilerplate (2026 Guide) Starting a SaaS from zero is a massive energy drain. You spend the first two weeks setting up logins, wrestling with database schemas, and fighting with Stripe APIs. By the time you’re ready to build your actual product, you’re already exhausted. This is why I always use a **pre-built application scaffold** for new projects. Instead of wasting weeks on infrastructure, I can launch a working MVP in a single weekend. But not every starter kit is worth the money. Here is my framework for choosing a foundation that won't turn into a maintenance nightmare six months down the line. --- ## What are the benefits of using a pre-built application scaffold? Before you write a single line of code, you should understand why the world's most productive developers use starter kits. The **benefits of using a pre-built application scaffold** include: 1. **Tested Security:** Authentication is hard. Pre-built solutions use battle-tested libraries like Better Auth or Clerk. 2. **Integrated Payments:** Most kits come with Stripe webhooks already configured, so you can start charging users immediately. 3. **Modern Architecture:** You get a clean, scalable folder structure (like the Nuxt 4 `app/` directory) that is ready for growth. 4. **AI Compatibility:** Modern scaffolds are designed to be "AI-native," making it easy for tools like Cursor or Claude to help you code. --- ## How to Choose the Right Kit for Your Project Not all starter kits are created equal. When deciding **how to choose a pre-configured solution for web development**, consider these factors: ### 1. Technology Stack Alignment Does the kit use tools you actually want to use? In 2026, the gold standard for Nuxt is: - **Framework:** Nuxt 4 - **Database:** Postgres (with Drizzle or Prisma) - **UI:** Nuxt UI or Tailwind CSS - **Auth:** Better Auth or Auth.js ### 2. Ease of Customization Some kits are "opinionated" and hard to change. Look for a kit like **ShipAhead** that provides a clean foundation without forcing you into a specific way of building your core logic. ### 3. Documentation and Support A fast start is only possible if you don't get stuck. High-quality kits provide searchable documentation and a community or direct support line. --- ## Best options for quickly starting a new web project If you are looking for the absolute **best options for quickly starting a new web project** in 2026, here are our top recommendations: - **ShipAhead:** Best for solo founders and AI-driven development. - **supastarter:** Best for complex enterprise requirements. - **Nuxt SaaS Kit:** Best for content-heavy SaaS. --- ## Step-by-Step: From Scaffold to Launch Once you have chosen your **pre-configured solution**, the path to launch is simple: 1. **Initialize:** Clone the repository and install dependencies. 2. **Configure:** Add your API keys for Auth, Database, and Payments to your `.env` file. 3. **Customize:** Replace the placeholder branding with your own and start building your unique features. 4. **Deploy:** Connect to Vercel or Cloudflare and go live. --- ## Conclusion: Stop Configuring, Start Building The biggest mistake founders make is building for too long in private. Using a **pre-built application scaffold** lets you get your product in front of customers while the idea is still fresh. You should be spending 90% of your time talking to users and 10% coding the infrastructure. A high-quality **Nuxt SaaS boilerplate guide** flips the ratio in your favor. Ready to ship? [Get ShipAhead](https://shipahe.ad){rel=""nofollow""} today and see how fast you can really move. # Buy a Nuxt boilerplate or build from scratch? The ROI math ![Should you buy a Nuxt boilerplate or build from scratch? See real ROI math, must-ship features, time-to-market tradeoffs, and a clear buy vs build checklist.](https://shipahe.ad/images/blog/buy-a-nuxt-boilerplate-vs-build-from-scratch-roi-math/post-777.webp){style="max-width:100%;border-radius:12px"} You want to ship a paid Nuxt app fast without cutting corners on authentication, payments, and admin. The question is not whether you can build it. It is whether building it yourself beats the return of buying a finished Nuxt SaaS starter and spending your time on the part users actually pay for. ## Buy vs build at a glance | Criteria | Buy a Nuxt boilerplate | Build from scratch | | --------------------- | ---------------------------------------------------------------------------------------------------- | --------------------------------------- | | Initial build hours | 10 - 25 hours to customize | 120 - 200+ hours for core SaaS plumbing | | Upfront cost | One-time license | Your time cost or contractor bill | | Features on day one | Auth, payments, admin, emails, i18n, analytics, cron, file storage, ORM, SEO, landing page, AI tools | Only what you have finished so far | | Time to first revenue | Days | Weeks or months | | Change risk | Lower. Proven flows you adapt | Higher. You design and test everything | | Lock-in | Editable source. Check license | Your own code, full control | ## ROI math you can check in an afternoon Here is a practical baseline for a Nuxt SaaS. These are conservative hour ranges for a senior developer who has done this before. If you are newer to Nuxt or backend work, expect higher numbers. - Authentication and protected routes: 16 - 28 hours for email + password, magic links, Google, sessions, route guards, CSRF. - Payments and checkout: 24 - 40 hours for subscriptions and one-time, taxes, coupon codes, metered usage, webhooks, retry logic, plan upgrades and proration. - Admin area: 16 - 24 hours to search users, view events, manage roles, and ban abusers. - Transactional email: 8 - 12 hours for password reset, email verification, welcome, and billing notices with templates and sandbox testing. - Internationalization: 8 - 12 hours for i18n config, route strategy, locale switcher, and translation loading. - Database and ORM: 10 - 16 hours for schema design, migrations, seed data, and type-safe queries. - File storage: 8 - 12 hours for S3-compatible uploads with presigned URLs, size limits, and secure access rules. - Analytics: 6 - 10 hours to track signups, activations, and funnel events with privacy controls. - SEO automation: 6 - 10 hours for meta tags, Open Graph images, sitemap, robots, canonical tags. - Cron and background jobs: 6 - 10 hours for scheduled reports, churn follow-ups, and cleanup tasks. - Prebuilt landing page: 4 - 8 hours to ship a responsive page with pricing and FAQ. - AI features: 10 - 20 hours to wire chat and text or image generation with model switching and usage limits. Total: 122 - 202 hours just to reach parity with a solid starter. At $100 per hour, that is $12,200 - $20,200 of opportunity cost. At $60 per hour with contractors, you still spend $7,320 - $12,120 before you build a single differentiating feature. A one-time license plus 10 - 25 hours of tailoring is a different curve. To make the decision concrete, run this back-of-the-envelope check: - Hours saved = 122 - 202 − customization\_hours. With 20 hours of customization, you save 102 - 182 hours. - Dollar value saved = hours\_saved × your\_hourly\_rate − license\_cost. - Break-even users for month one = license\_cost ÷ (price\_per\_month × margin\_after\_fees). Example assumptions for illustration: license $399, your time $100/hour, subscription price $19/month, payment fee 5% effective after card + platform fees, so margin ≈ 95%. - Hours saved: 102 - 182 ⇒ value saved: $10,200 - $18,200. After license, $9,801 - $17,801 net. - Break-even users in month one: $399 ÷ ($19 × 0.95) ≈ 22 users. If you can pull in 25 users in the first month by launching earlier, the license pays for itself before you would have finished wiring webhooks. If your rate is $40/hour, the math still clears: 102 hours saved is $4,080; subtract the license and you are ahead, with weeks back on the calendar. ## What you must ship on day one “MVP” should not mean skipping critical flows. A paid app needs more than a login form and a pricing page. Your baseline list, and how a Nuxt starter compresses it: - **Authentication and protected pages.** Email + password, magic links, OAuth, password reset, device sign-out, secure server routes, and route rules. - **Payments.** Subscriptions and one-time charges with trials, coupons, tax, receipts, and idempotent webhooks. Providers should be swappable. - **Admin panel.** User search, flags, impersonation for support, and audit logs. - **Transactional email.** Ready templates and environment toggles so you do not ship with test keys. - **i18n.** Locale-aware routing, per-locale SEO tags, and a visible switcher. - **Database and ORM.** Typed models, safe migrations, and seeds for local dev and CI. - **File storage.** S3-compatible uploads with presigned URLs and automatic cleanup for abandoned uploads. - **Analytics and SEO.** Events for activation, onboarding steps, and churn reasons, plus automatic meta, Open Graph, and a sitemap. - **Cron and background jobs.** Scheduling for digests, reminders, and billing checks without ad-hoc scripts. - **Marketing surface.** A fast landing page, pricing, and a content section so you can ship updates and rank. - **AI tools.** Chat and generation endpoints with usage caps, per-plan limits, and simple provider switching. shipahe.ad’s Nuxt SaaS starter kit ships this checklist on day one, so your time goes into product logic, not scaffolding. ## Speed, focus, and risk after launch Time-to-market is not just a nicer calendar. It is cash flow, iteration speed, and a smaller risk surface. - **Faster feedback.** Shipping in two weeks instead of eight gives you six extra weeks of data. That usually means tighter onboarding, clearer pricing, and fewer dead-end features. - **Focus where it counts.** Every hour not spent on auth and billing can go to the hard parts of your app: your model, your UI, your workflow. - **Reduced incident load.** Authentication, billing, and file storage are where early outages hide. Starting from proven flows lowers production surprises. - **Change without fear.** Typed models, real migrations, and swappable providers make it easier to refactor pricing, expand to new regions, or add an enterprise plan. - **Team ramp-up.** A consistent Nuxt structure helps new contributors get productive quickly. Compatibility with AI coding tools like Cursor and Claude can speed routine refactors. ### How to ship an AI tool this week with a Nuxt starter Pick one narrow use case, for example “rewrite product descriptions for Etsy.” Wire your input form to the built-in chat or text generation endpoint. Set two plans (free trial with limits, $19/month for higher limits). Enable protected pages and checkout. Publish the prebuilt landing page with a short demo video. Track activation and first success in analytics, add a cron job to email inactive trials on day 2 and day 5, then translate the UI for your second market using the locale switcher. You will learn more from 50 real users than from two extra weeks of local tinkering. ## How to evaluate a boilerplate, and when to build instead Treat the purchase like hiring a developer to write your baseline code. Verify fit before you buy. - **Feature parity.** Check for email + magic link + OAuth auth, protected pages, subscriptions and one-time, admin, transactional email, i18n, analytics, cron, file storage, ORM, SEO, AI features, and a landing page. - **Code quality.** Look for a typed codebase, clear folder structure, realistic examples of checkout flows and webhooks, and tests for critical paths. - **Swap-ability.** Payments and AI providers should be replaceable without rewrites. - **Docs and examples.** README, environment samples, and copy-paste snippets reduce setup time. - **License and scope.** Read it. Confirm commercial use, number of apps allowed, client work rights, and update policy. - **Maintainability.** Migrations, background jobs, and analytics should be first-class, not bolted on. When to build from scratch: you have a nonstandard architecture, strict compliance that demands bespoke flows, or runway for 120 - 200+ hours of foundation work. In every other case, buy the boilerplate, customize, and ship. ### Key takeaways - Buying a Nuxt boilerplate typically saves 100+ hours and pulls launch forward by weeks. - The must-have SaaS features are already built, tested, and wired together. - Earlier launch means earlier revenue and faster learning cycles. - Do the math: hours\_saved × rate − license\_cost, and a simple break-even user count. - Read the license, confirm provider swap-ability, and focus on what makes your app worth paying for. ## FAQ ### Is buying a Nuxt boilerplate worth it for a solo founder? Yes if you value time. It replaces 100+ hours of scaffolding with a few days of setup, so you can focus on the feature that makes your app worth paying for. ### Will I be locked into a vendor if I start with a boilerplate? You get a codebase you can modify. Still, read the license and confirm you can ship commercially and change payment providers or AI models later. ### How fast can I launch using a Nuxt SaaS starter kit? Many teams can go live in days. Most of the time goes to customizing copy, pricing, and onboarding rather than building auth, payments, and admin. ### What security concerns should I check before buying? Review how authentication, sessions, and protected routes are implemented. Check webhook handling for payments and confirm secure file storage settings. ### How do I add custom features on top of a starter kit? Start from the typed models and routes the kit provides. Add new modules, migrations, and UI, and reuse existing patterns for auth, billing, and emails. # Buy vs build Nuxt starter kits: ROI, timeline, and revenue ![Founder case study quantifies buy vs build Nuxt: 300 vs 80 hours, 15-day launch, earlier revenue, and clear ROI from a Nuxt SaaS starter kit.](https://shipahe.ad/images/blog/buy-vs-build-nuxt-starter-kits-roi-and-time-to-market/post-309.webp){style="max-width:100%;border-radius:12px"} Every founder building on Nuxt faces two clocks. The hours it takes to ship auth, payments, and admin, and the days until first revenue. This is our quantified case study. We compared building from scratch to buying a Nuxt SaaS starter kit, then shipped paid checkout in 15 days. Below are the inputs, assumptions, and results so you can decide with numbers, not vibes. ## Team, product, and guardrails We were two senior full-stack engineers and a part-time designer. The product was a focused AI assistant for drafting outbound messages. Stack was Nuxt and Vue. Goal was strict. Paid MVP in four weeks to test pricing and positioning. One third of our waitlist was outside the US, so we needed i18n from day one. We aimed for production-grade foundations, not prototypes. Non-negotiables that defined scope and risk: - Authentication: email and password, passwordless magic links, Google OAuth, email verification, session hardening, rate limiting, and tests. - Payments: Stripe subscriptions and one-time credits, proration, taxes and invoices, dunning, refund flows, webhook signature verification, and idempotency guards. - Data: PostgreSQL with a typed ORM and migrations, seeds, and a clean repository pattern. - File storage: S3-compatible signed uploads, private buckets, access policies, and basic lifecycle rules. - Emails: transactional provider with templated password reset, welcome, and receipt emails, plus event-driven triggers. - Admin: users table with search and filters, impersonate user, role management, refunds, and spam bans. - Internationalization: Nuxt i18n with a language switch, runtime locale detection, and translated system strings. - Analytics: page and event tracking for signups and checkout, and a baseline funnel. - SEO: per-page meta, Open Graph images, sitemap, robots rules, and canonical URLs. - Jobs: scheduled tasks for summaries and reminders with retries and visibility. - Content: simple blog and docs using Nuxt Content for release notes and help. - AI: chat and generation with provider switching, token accounting, and safe moderation defaults. - Deployment: preview environments, environment variables, logging, and error tracking. We could build it all, or start from a Nuxt SaaS starter kit like Shipahe.ad that ships these pieces in a consistent, typed codebase and is designed to work with AI coding tools like Cursor and Claude. The goal was not to outsource product thinking. It was to delete undifferentiated engineering work. ## Cost model: build vs buy Assumptions were conservative. Two experienced developers. Code reviews and tests included. No gold plating, but production ready. - Auth and protected routes: 50 hours for signup, login, magic links, Google, email verification, password reset, session guards, and tests. - Payments and checkout: 60 hours for subscriptions and one-time, customer portal, plan changes, invoices and tax, dunning, webhooks, retries, and test matrix. - Database and ORM: 22 hours to set up PostgreSQL, typed models, seeds, migrations, and local scripts. - File storage: 12 hours for S3-compatible uploads, signed URLs, and UI integration. - Admin panel: 24 hours for users list, roles, impersonation, refunds, and bans. - Transactional emails: 16 hours for templating, events, and environment configuration. - Internationalization: 12 hours for wiring locales, toggle, and key extraction. - Analytics: 8 hours for page, event, and funnel tracking. - SEO: 8 hours for meta, OG image generator, sitemap, and robots. - AI chat and generation: 24 hours for UI, server endpoints, provider switching, and moderation. - Scheduled jobs: 6 hours for cron tasks, retries, and observability. - Blog with Nuxt Content: 10 hours for routes, SEO, and styling. - Marketing page: 8 hours for a customizable landing page with pricing blocks. Subtotal was about 260 hours. Add 15 percent for glue work across flows like webhooks, emails, and edge cases. Total landed near 300 hours. At a blended internal rate of 90 dollars per hour, that is about 27,000 dollars before touching core AI logic. With a starter kit like Shipahe.ad, we still had to remove what we did not need, wire our domain logic, and make it ours. Estimated effort: - Branding and landing page customization: 8 hours. - i18n copy and layout review: 6 hours. - Auth options and route guards: 10 hours. - Stripe plans, checkout, and webhook tests: 12 hours. - Database models, seed data, and file storage toggles: 8 hours. - Analytics and SEO configuration: 4 hours. - Transactional emails and a short welcome drip: 6 hours. - Cron jobs for summaries: 3 hours. - AI workflow using provided patterns: 12 hours. Total was about 69 hours to have foundations in place. Even if it stretched to 80 hours, the delta stayed near 220 hours. At 90 dollars per hour, that is 19,800 dollars of engineering time not spent on boilerplate. The license fee was tiny compared to the saved hours. ## Timeline to MVP We held a four-week target to paid users. Buying did not remove work, it moved it to what matters. ### If we built everything ourselves - Week 1: Auth, protected routes, database scaffolding, and email provider setup. - Week 2: Payments, checkout, invoices, and first end-to-end tests. - Week 3: Admin panel, file storage, and transactional emails. - Week 4: i18n, analytics, SEO, and scheduled jobs. - Week 5: AI chat and generation with model switches and moderation, marketing page, and blog. - Week 6: QA, refactors, perf passes, and production hardening. Best case was six weeks for an acceptable MVP, more likely seven to eight with polish and bug fixes. ### If we bought a Nuxt SaaS starter kit - Days 1 to 2: Customize landing page, set language toggle, ship a short blog post. - Days 3 to 5: Configure auth variants and route guards. Invite internal testers. - Days 6 to 8: Set up Stripe subscriptions and one-time credits. Verify webhooks and test dunning. - Days 9 to 10: Build the AI chat and generation flow end to end. - Day 11: Enable analytics and confirm SEO checks pass. - Day 12: Wire transactional emails. Test password reset and welcome. - Day 13: Review admin panel, set moderation rules, add summaries via cron. - Day 14: Bug bash, connect domain, ship. The kit was built to pair with AI coding tools like Cursor and Claude. We used Cursor for refactors and repetitive edits, such as translating strings and adjusting email templates. It sped up routine work without skipping reviews. We hit production in 15 days with paid checkout working. ## Maintenance, security, and updates Foundations create a long tail. Auth edge cases, Stripe API version bumps, email template tweaks, and localization fixes all show up after launch. With bespoke code, we expected 6 to 8 hours a week of maintenance in the first quarter. That includes dependency updates, triage, and support scripts. With a consistent, typed codebase that already included ORM patterns, transactional emails, analytics, SEO, and scheduled jobs, weekly maintenance landed near 2 to 3 hours. The admin panel cut support back-and-forth because we could impersonate a user, issue refunds, or ban spammers without ad hoc scripts. i18n with an in-app toggle made content changes low friction. The blog on Nuxt Content covered release notes without standing up a CMS. Deciding what to build next was another source of waste. A simple feature voting board gave us signal without meetings. We leaned on Feedjolt’s overview of the [best feature voting tools to surface real product demand](https://www.feedjolt.com/en/blog/best-feature-voting-tools-to-surface-real-product-demand){rel=""dofollow""} to pick a lightweight setup that fit our size and avoided roadmap bloat. ## ROI, payback, and decision The numbers close the loop. Launching with a Nuxt starter kit let us buy boilerplate instead of building it. We shipped in 15 days. In the first 30 days live, analytics showed 1,240 unique visitors. Signups converted at 8.6 percent. Paid conversion was 3.1 percent. That produced 33 subscriptions and 18 one-time purchases for a first-month revenue of 2,190 dollars. On the build-everything path, first revenue would have landed around week seven or eight. Engineering time saved was about 220 hours in the first release. At 90 dollars per hour, that is 19,800 dollars of avoided cost. Pulling revenue forward by four weeks added about 2,000 dollars in cash flow and gave us conversion data for pricing. Even if our build-from-scratch estimate was 25 percent too high, buying still wins by a wide margin. The license paid for itself in the first week. The most important outcome was focus. Because foundations were present, we spent energy on the differentiator, the AI chat and generation workflow. We iterated prompts, added model switches, and tuned UX flows that mattered to users. If you are asking whether to buy or build Nuxt for a new product, our conclusion is clear. For a small team trying to ship and learn fast, buying a Nuxt SaaS starter kit is the higher-ROI path. ### Key takeaways - Scope is larger than it looks. Auth, payments, admin, analytics, SEO, and i18n total about 300 hours when built from scratch. - Starting from a Nuxt starter kit cut foundation time to about 70 to 80 hours, saving roughly 220 hours. - We reached paid users in 15 days and pulled revenue forward by about four weeks. - A Nuxt SaaS template with AI chat patterns lets you focus effort on core product value. - Use a lightweight feature voting board to guide roadmap with real demand signals. ## Recommended resources - [best feature voting tools to surface real product demand](https://feedjolt.com) # Cursor + Nuxt: Prompts and Workflows to Ship SaaS Faster ![Use Cursor with a Nuxt SaaS starter kit to scaffold routes, auth, billing, i18n, emails, admin, and more so you can ship a paid product fast.](https://shipahe.ad/images/blog/cursor-nuxt-prompts-and-workflows-to-build-saas-faster/post-835.webp){style="max-width:100%;border-radius:12px"} You do not need help writing your core feature. The drag is the scaffolding around it: routes, auth, billing, i18n, admin, uploads, and the copy and tests that glue it together. Pair Cursor with a Nuxt SaaS starter kit and you can turn that plumbing backlog into a handful of prompts you can run before lunch. ## Set up Cursor with the right Nuxt context Start by giving Cursor a one-page brief that describes your stack, folder layout, and house rules. Include Nuxt version, TypeScript, linting settings, and where business logic lives. Spell out conventions so Cursor names things the way you do. Example details to include: - Folders and routes: `/pages` for routes, `/layouts/default.vue` and `/layouts/auth.vue`, `/middleware/auth.global.ts`, `/server/api/*` for endpoints, `/components/ui/*` for shared UI. - State and data: Pinia in `/stores/*`, ORM in `/server/db/*`, Postgres via Prisma in `prisma/schema.prisma`. - Runtime config: public keys in `runtimeConfig.public`, secrets in `runtimeConfig`, `.env.example` kept in sync. - Testing: unit tests with Vitest in `/tests`, component tests in `/components/__tests__`. Then ask Cursor to map the repo and create an `docs/architecture.md` that lists: - Route patterns and dynamic params, e.g. `/account`, `/admin/users/[id]`. - Shared layout slots and their purpose. - Auth boundaries and which middleware runs where. - Where environment variables are read and validated. Use a diff-first rule: “Before writing, show the file list and a unified diff, explain risky changes, and propose a commit message.” This keeps edits traceable as the repo grows. ## Ship the core screens in one pass Turn the first mile into a single prompt that scaffolds your base routes and ties them to your layout and SEO utilities. Ask Cursor to create or update: - Public pages: `/pages/index.vue` (home), `/pages/pricing.vue` (pricing), `/pages/legal/[slug].vue`. - Auth pages: `/pages/login.vue`, `/pages/register.vue`, `/pages/reset-password.vue`. - App pages: `/pages/dashboard/index.vue`, `/pages/account/index.vue`, `/pages/admin/index.vue`. If your starter ships a landing page, keep its structure and only swap copy and media. Wire titles and descriptions with `useSeoMeta` so Open Graph and Twitter tags are set from page data. Ask for a tiny OG image endpoint in `/server/routes/og.ts` that renders a title and brand color so you do not hunt for images later. Have Cursor create a small set of typed, reusable components with minimal props and examples in comments: - `components/ui/AppButton.vue` with `variant`, `size`, and `loading`. - `components/pricing/PricingTable.vue` that accepts an array of plans and emits `select` with the plan id. - `components/forms/TextField.vue` with label, help text, and `v-model`. Ask Cursor to include a usage note below each component block so future prompts reuse them rather than duplicating UI. Consistency is free speed. ## Wire the hard parts once: auth, billing, i18n, uploads, emails Authentication. Prompt Cursor to implement sign up, sign in, sign out, and password reset using the kit’s auth provider. Cover email+password, magic links, and Google. Guard protected pages with `auth.global.ts` and redirect new users to `/onboarding`, returning users to `/dashboard`. Add server-side checks in admin routes, not only middleware. Billing. Keep the implementation provider-agnostic. Ask Cursor to: - Create `/pages/pricing.vue` that renders plans from `~/config/plans.ts`. - Implement `/server/api/billing/create-checkout-session.post.ts` that accepts a `planId` and returns a redirect URL. - Add success and cancel pages at `/pages/checkout/success.vue` and `/pages/checkout/cancel.vue` with simple state messaging. - Handle webhooks in `/server/api/webhooks/billing.post.ts`, updating `User.subscriptionStatus` and `plan`. - Expose a `useBilling()` composable to query subscription status and gate premium features. Localization. Ask Cursor to extract visible strings into `/locales/en.json` and another locale you plan to support, for example `es.json`. Provide a glossary for product terms so translations stay consistent. Add a language switcher in the header that persists the choice and falls back to browser language. Include number, date, and currency formatting in `plugins/i18n.ts` so pricing renders correctly across locales. Uploads. Implement secure file uploads with S3-compatible storage. Ask Cursor to: - Create `/server/api/uploads/sign.post.ts` that validates content type and size, returns a signed URL, and stores metadata in your ORM. - Build `components/uploads/AvatarUploader.vue` that uses the signed URL, shows progress, and updates the profile. - Restrict read access server-side so users can only fetch their own files. Add an allowlist for MIME types. Emails. Use the starter’s email templates. Ask Cursor to draft welcome, password reset, and receipt emails in `/emails/*`, each with a text fallback. Wire `sendPasswordReset` and `sendWelcome` in your auth flows and add a simple preview route in dev that renders templates with fake data. Store provider keys in runtime config and make `.env.example` accurate. ## Build growth loops and reliability early Analytics. Ask Cursor to add a lightweight `useAnalytics()` composable that tracks `page_view`, `signup`, `checkout_started`, `subscription_activated`, and your core feature actions. Add calls in page hooks and in the billing flow. Create a small tile on the dashboard that shows yesterday vs today for signups and activations so you can see movement without opening another tool. Content and SEO. Turn on the blog with Nuxt Content. Ask Cursor to generate a `content/blog/` structure with front matter for title, description, and `og:image`. Draft one practical post that matches your feature, like a walkthrough that your pricing page links to. Let your SEO helper create meta tags and sitemap entries automatically. Mirror the i18n setup so content ships in multiple languages using the same pipeline. Cron jobs. Describe the recurring work you need: daily summaries, a weekly report, and nudges for inactive users. Ask Cursor to create scheduled tasks that call your server functions and log outcomes to a simple table. Route results into your email templates. Keep retry logic simple: exponential backoff and a max attempts count written next to the job code so failures are visible. Admin. Request a basic admin dashboard that lists users with filters for plan and status, includes a ban action with a reversible flag, and shows last login time. Add server-side permission checks in `/server/api/admin/*` and a tiny audit log when admin actions run. ## A diff-first workflow that stays fast Speed comes from small, safe steps. Keep prompts narrow and ask for diffs, risks, and tests. Make Cursor follow a checklist that mirrors the starter kit: auth, protected pages, billing, emails, i18n, admin, analytics, SEO, storage, cron jobs, and optional AI features. Concrete workflow that works for small teams: - Setup (90 minutes): write the project brief, get a repo map, and agree on file naming and commit message patterns. - Core routes (60 minutes): scaffold pages, layouts, nav, and SEO meta wiring. - Auth and billing (2 - 3 hours): flows, middleware, success and cancel routes, webhooks, and a plan-aware dashboard. - Polish (2 hours): i18n extraction, avatar uploads, transactional emails, and analytics events. - Growth (1 hour): blog enabled, a starter post drafted, and a weekly cron that sends a usage report to you. If your backlog reads like a plumbing checklist, buy a Nuxt boilerplate that already ships the foundations and is shaped for Cursor. You will spend your prompts on product decisions instead of wiring. The result is a working SaaS you can price and share, not another weekend of setup. ### Key takeaways - Give Cursor a clear Nuxt brief and ask for diffs, risks, and commit messages before it writes. - Scaffold core pages, layouts, and SEO in one pass, then reuse a small set of typed UI components. - Implement auth, billing, i18n, uploads, and emails once with provider-agnostic server routes and strict middleware. - Add analytics, a blog, and cron jobs early so you see signal and drive retention from day one. - Use a checklist that mirrors the starter kit and keep prompts small so speed does not break safety. ## FAQ ### What is Cursor and how does it help with Nuxt? Cursor is an AI coding editor that can read your repo and propose edits. With a clear project brief, it can scaffold Nuxt pages, wire middleware, and generate consistent components faster. ### Can I use Cursor with a Nuxt SaaS starter kit? Yes. A Nuxt SaaS starter kit that’s designed to work with AI coding tools lets Cursor handle auth, payments, i18n, emails, and more through targeted prompts. ### How do I prompt Cursor to set up authentication in Nuxt? Point it to the starter kit’s auth files, describe the flows you want, and ask it to add middleware for protected pages. Request diffs first, then test sign up, sign in, and reset. ### Is it safe to let an AI edit my Nuxt repo? Keep edits diff-first and small, require file citations, and review before saving. This workflow is safe and helps you catch regressions early. ### How do I build and sell an AI tool online with Nuxt? Start with a Nuxt starter kit that includes AI chat, text, and image modules plus payments. Use Cursor to connect the flows, add pricing, and publish a landing page. # Deploy Nuxt to Vercel: environments, secrets, and rollbacks ![Deploy Nuxt to Vercel the right way: env vars, SSR, previews, SEO-safe robots, payments, emails, and rollbacks. A practical flow we use to ship SaaS.](https://shipahe.ad/images/blog/deploy-nuxt-to-vercel-environments-secrets-rollbacks/post-864.webp){style="max-width:100%;border-radius:12px"} Deploying Nuxt to Vercel is easy to click through and hard to get right. The usual traps are secrets leaking to the client, preview builds showing up in Google, and a hotfix breaking checkout with no quick way back. Here is the deployment flow we use in our own Nuxt SaaS boilerplate to move from local to preview to production fast, with a clean rollback plan. ## Set up environment variables and secrets correctly ### Keep client and server config separate Nuxt exposes variables prefixed with **NUXT\_PUBLIC\_** to the browser. Everything else stays server side. Treat this as a hard rule. - Client: `NUXT_PUBLIC_APP_URL`, `NUXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`, `NUXT_PUBLIC_SENTRY_DSN` - Server: `DATABASE_URL`, `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `OAUTH_GOOGLE_CLIENT_SECRET`, `RESEND_API_KEY` or `SMTP_PASSWORD`, `S3_SECRET_ACCESS_KEY` Never expose API keys for payments, OAuth, or AI providers on the client. If you need a value in the browser, proxy it through an API route. ### Use Vercel’s env scopes Define variables separately for Development, Preview, and Production. Use test credentials in Preview and real credentials in Production. Typical sets: - App URLs: `NUXT_PUBLIC_APP_URL`, `NUXT_PUBLIC_API_URL` - Payments: Stripe publishable key, secret key, webhook signing secret - Auth: OAuth client IDs and secrets for each provider - Storage: S3 endpoint, bucket name, access key, secret - Email: SMTP host, username, password or API key for your provider CLI makes this safe and repeatable: - `vercel env add` to create keys - `vercel env pull .env.local` to sync to a local file per teammate Do not commit any `.env*` files. Rotate secrets in all three scopes and redeploy when you change a key. ## Configure Nuxt and Vercel to build the same way ### Pin Node and package managers Use an LTS Node that Vercel supports, and pin it so local, CI, and Vercel match. In `package.json`: ``` ``` Use `pnpm install --frozen-lockfile` or `npm ci` to prevent surprise upgrades at build time. ### Nuxt settings that avoid surprises - SSR: Keep SSR on for SaaS. You need protected pages, cookie-based auth, and fast first render. - Nitro preset: Vercel is auto-detected, but being explicit helps when debugging. ``` ``` - Serverless awareness: The filesystem is ephemeral and functions can cold start. Store uploads on S3-compatible storage. Keep API handlers short. Offload heavy work to background jobs or scheduled functions. - Edge vs serverless: Only run pure web APIs at the Edge. Anything using Node libraries, SDKs, or database drivers should run on serverless functions. ### Production-like local dev Use the same env var names locally that you use on Vercel. Run your app with `NUXT_PUBLIC_APP_URL=http://localhost:3000` so callback URLs and email links mirror real flows. ## Use Preview deployments for QA, payments, and i18n ### Every pull request gets its own URL Vercel creates a unique Preview URL per branch. Treat it like a staging site and run a checklist: - Auth: sign up, sign in, sign out, password reset, OAuth callback - Admin: view users, upgrade or cancel a test account, ban a spammer - Payments: subscribe and cancel with Stripe test cards, verify webhooks end to end - i18n: switch languages and confirm all strings translate, including emails - Uploads: create, view, and delete a test file, confirm it lands in your bucket ### Keep previews out of search Block indexing on non-production. You can set an X-Robots-Tag header from server middleware based on Vercel’s environment: ``` ``` Also disable sitemap generation outside Production. If you use a sitemap or SEO module, guard it with `process.env.VERCEL_ENV === 'production'`. When you ship to your real domain, publish correct titles, meta descriptions, Open Graph images, and a sitemap. ### Verify analytics and email Send a welcome email, a password reset, and a receipt from Preview. Check SPF, DKIM, and DMARC status in your email provider before launch day. For analytics, confirm page views, signups, and key events appear in your dashboard in both Preview and Production. ## Promote to Production safely and keep SEO clean ### Lock production settings before traffic - Payments: swap to live keys and live webhooks in Vercel’s Production scope - App URL: make sure `NUXT_PUBLIC_APP_URL` matches the primary domain - Email: use a verified sending domain with valid SPF, DKIM, DMARC - Domain: map the custom domain and confirm HTTPS on `www` and apex ### Promote the exact build you tested Use Vercel’s Promote to Production from a known-good Preview. That removes the risk of a fresh build changing dependencies. After traffic starts, smoke test auth, protected routes, and the admin area. Watch cold starts on first hits to dynamic routes. ### Ship more than a landing page on day one If you use a Nuxt SaaS starter kit, you can launch with auth, billing, i18n, an admin panel, SEO automation, analytics, emails, file storage, and scheduled jobs already wired. That lets you watch real users within hours and refine pricing or onboarding based on data, not guesses. ## Monitor, roll back fast, and protect data ### Logs, jobs, and user actions Open Vercel logs right after each deploy. Track signups, activations, and core feature events. If you run scheduled jobs for reports or reminders, confirm they fire on time and complete within function limits. ### Rollbacks that do not corrupt data Rolling back code in Vercel is instant. Data is not. Treat migrations as forward only: - Run migrations in Preview against a preview database before merging - Deploy code that can read both old and new columns during the transition - Use idempotent scripts to backfill data, and monitor them If a Production deploy misbehaves, promote the last healthy deployment in Vercel and investigate with logs and error tracking before retrying. ### Close the loop on revenue and support Test checkout in Production with a small live plan, then cancel it. Check invoices, receipts, and proration. Ensure the admin can view accounts, issue credits, and ban abuse. After launch, improve your demo videos too. A clear subtitle track lifts retention on product tours. This [Video SEO captions that boost watch time: a practical guide](https://subtitlesfast.com/blog/video-seo-captions-9-proven-tips-to-boost-watch-time){rel=""dofollow""} covers auto captions for TikTok and YouTube and shows how styled, burned-in subtitles from a web-based AI editor help viewers finish your videos. ### Common pitfalls to avoid - **Leaking secrets to the client.** Only expose variables with a NUXT\_PUBLIC\_ prefix. - **Ephemeral storage surprises.** Never write user files to the server filesystem. Use S3-compatible storage. - **Indexing preview builds.** Add an X-Robots-Tag noindex header and skip sitemaps outside Production. - **Node drift.** Pin a single Node LTS across local, CI, and Vercel. - **Long-running AI calls.** Add timeouts, retries, and move heavy generation to background jobs. - **One-way migrations.** Test on a preview database and deploy in small steps. - **Assuming local equals SSR.** QA cookies, protected routes, and OAuth on a real Preview URL. ### Key takeaways - Scope secrets per environment and only expose NUXT\_PUBLIC\_ vars to the browser. - Pin Node and make Nuxt’s serverless boundaries explicit for uploads and long tasks. - Use Vercel Previews to QA auth, payments, emails, i18n, and admin before you ship. - Promote a tested Preview to Production and keep a known-good rollback target ready. - Production-ready SEO, analytics, and emails let you learn from real users on day one. ## FAQ ### What build and output settings do I need to deploy Nuxt on Vercel? Use the Nuxt framework preset with a standard install command and npm run build. Keep SSR enabled for SaaS apps so auth, protected routes, and dynamic pages work. ### How should I handle environment variables for Preview vs Production? Set separate variables in Vercel for each environment. Use test keys in Preview and live keys in Production. Only expose NUXT\_PUBLIC\_ variables to the client. ### Do I need to change anything for file uploads on Vercel? Yes. The filesystem is ephemeral. Use an S3-compatible storage service for user uploads and generated files, and store only URLs in your database. ### What is the safest way to roll back a bad deployment? Promote a previously successful deployment in the Vercel dashboard. Be careful with database migrations since code rollbacks are instant but data rollbacks are not. ### Can I use this setup to launch an AI tool for sale? Yes. Deploy the Nuxt app, wire payments, and add AI chat or generation features. Validate quickly with production-ready analytics, SEO, and transactional emails. ## Recommended resources - [Video SEO captions that boost watch time: a practical guide](https://subtitlesfast.com) # Deploy Nuxt to Vercel with Custom Domains, Step by Step ![Ship a Nuxt 3 app on Vercel with correct build scripts, env vars, custom domains, previews, caching, redirects, and safe rollbacks. Clear, tested steps.](https://shipahe.ad/images/blog/deploy-nuxt-to-vercel-with-custom-domains-step-by-step/post-375.webp){style="max-width:100%;border-radius:12px"} Shipping a Nuxt 3 app on Vercel is quick if you line up build scripts, runtime config, and DNS the right way. This is the exact deployment flow we use for SaaS apps with auth, payments, i18n, and admin. Follow it once, then repeat it for every feature branch and release without surprises. ## 1) Prepare your Nuxt project for Vercel Lock the basics so your cloud build matches your local build. ### Match Node versions - Use Node 18 or 20. Pick one and use it everywhere. - Add an engines field or an *.nvmrc* so teammates and CI use the same version. ``` ``` ### Set build and start scripts Vercel auto-detects Nuxt, but explicit scripts avoid edge cases. ``` ``` Before pushing, run a local production build to catch SSR issues early: ``` ``` ### Confirm SSR, image domains, and the Vercel preset Most SaaS apps need SSR for auth, server routes, and webhooks. Make that explicit and keep server-only code out of the client bundle. ``` ``` ### Keep server code server-only - Put API handlers under *server/api*. Each file becomes an endpoint. Test them locally with `curl` before you deploy. - Do not reference `window` or `document` in server code. Guard any client-only usage with `process.client` checks. - Enforce protected routes in server middleware so SSR does not leak restricted content. ### Clean artifacts before first deploy Delete *.nuxt* and *.output*, then rebuild. You want the same clean state Vercel will use. ## 2) Configure environment variables and runtime config Separate what the browser can see from what it cannot. Map everything to `runtimeConfig`. ### Define runtime config in Nuxt ``` ``` - Anything in `runtimeConfig.public` can be read in the browser. Only put non-sensitive values there. - On Vercel, variables prefixed with `NUXT_PUBLIC_` are exposed to the client. Everything else is server-only. ### Add env vars per Vercel environment - In Project Settings, add variables for Production, Preview, and Development. Use different keys for staging databases, payment test keys, and email sandboxes. - Use the CLI to sync values locally so your app behaves the same on your machine and in the cloud: ``` ``` ### Know what is read at build time vs request time - SSR pages and API routes read `runtimeConfig` on each request. - Prerendered routes capture values at build time. If a value must update without a rebuild, do not prerender that route. - Use a Preview deployment to test a config change without touching Production. ## 3) Domains, previews, redirects, and caching ### Add and verify your custom domain 1. In your Vercel project, add both the apex domain and the *www* subdomain. 2. Point DNS to Vercel: - Apex: A record to **76.76.21.21**. - www: CNAME to **cname.vercel-dns.com**. 3. Wait for propagation, then pick a primary domain and keep one canonical host. ### Set redirects and headers in Nuxt Keep SEO and analytics clean with a single host and predictable cache policy. Use Nuxt route rules so your config travels with the repo. ``` ``` You can also configure redirects in the Vercel dashboard if you prefer UI control. Keep the rule in one place to avoid conflicts. ### Use Preview deployments with real staging data - Connect your Git repo. Every push creates a unique Preview URL. Treat this as staging for product owners and QA. - Add Preview env vars so previews use staging databases and payment test keys. Never point Preview at production data. - If you need a stable preview hostname, attach a subdomain such as *preview\.example.com* to the Preview environment in Project Settings. ### Static assets - Ship hashed filenames so long-lived caching is safe. Nuxt handles this by default for built assets. - Whitelist any remote image domains to avoid production blocks. ## 4) Ship, verify, and monitor ### Deploy from Git or the CLI - Git-based flow: merge to your main branch to trigger a Production deployment. - CLI flow: `vercel` for a preview, then `vercel --prod` for production. ### Run the critical path checks - Open the homepage and a few deep links. Watch server logs in the Vercel dashboard for slow queries and missing assets. - Exercise APIs with valid and invalid inputs. Example: `curl -i https://yourdomain.com/api/health` and check status codes. - Auth flows end to end: sign up, email magic link, social login, password reset, gated routes. Confirm logout clears cookies and sessions. - Payments in test mode: create a plan, run checkout, verify webhooks update user entitlements and invoices. Confirm idempotency so retries do not double-charge. - Internationalization: switch locales, ensure dynamic routes and metadata render correctly on SSR. ### Turn on your platform features If you built on our Nuxt SaaS starter, you can switch on analytics, SEO meta and sitemap generation, scheduled cron jobs for reports or reminders, and transactional emails for password resets and welcomes immediately after go-live. These ship with the kit, so you do not have to glue them on later. If content and backlinks are your next bottleneck, teams often pair their app with RankGoat to write posts, secure dofollow links, and fix indexing so new features get discovered. ## 5) Roll back fast and avoid pitfalls ### Instant rollbacks Each Vercel deployment is immutable. If production is off, open the last known good deployment in the dashboard and promote it to Production. You can also point your production alias back to that deployment URL using the CLI. The switch is instant because both builds already exist. ### Common pitfalls to avoid - **Missing Preview env vars.** A feature works locally but fails on a branch because the variable only exists in Production. Mirror critical keys with safe staging values. - **Leaking secrets to the client.** Never pass server-only values via `runtimeConfig.public` or with a `NUXT_PUBLIC_` prefix. - **Remote images blocked.** Production will fail requests if domains are not whitelisted. Add them before launch. - **Wrong SSR vs prerender choice.** If a page must reflect per-request data, do not prerender it. If it is mostly static, give it ISR for speed. - **Large serverless bundles.** Keep server routes lean. Import only what you use. Move browser-only packages out of server code. - **No canonical redirect.** Redirect non-www to www or the reverse so SEO and analytics are not split. - **Node mismatch.** Teams on different Node versions see build-only bugs. Pin Node and use the same version in Vercel. ## Key takeaways - Lock Node, scripts, SSR, and image domains before connecting Vercel. - Store secrets in Vercel and map them to `runtimeConfig`. Keep Production and Preview separate. - Attach your custom domain, set one canonical host, and configure redirects in code or the dashboard. - Use route-level caching: ISR for mostly static pages, no-store for auth and APIs. - Rely on immutable deployments to roll back instantly when needed. # How to Build a Nuxt Module: Structure, Options, and Publishing ![Learn how to build a Nuxt module from scratch. Scaffold, add options, ship plugins and composables, test in a playground, and publish without headaches.](https://shipahe.ad/images/blog/how-to-build-a-nuxt-module-structure-options-and-publishing/post-680.webp){style="max-width:100%;border-radius:12px"} You copy the same plugin, composables, and config across projects. A Nuxt module lets you package that setup once so every app gets the same behavior with one install. This guide shows a practical module that registers a plugin, composables, and components, passes options to runtime, tests in a playground, and ships clean to npm. ## What a Nuxt module is and when to write one A Nuxt module runs at dev and build time to extend Nuxt. It can register plugins and composables, add components, ship server handlers to Nitro, tweak Vite and Nitro config, and inject runtime config for the host app. Choose a module when you want to: - Ship a reusable feature like analytics, feature flags, billing UI, or an API client. - Enforce conventions across a team, for example a UI kit, linting, and default build config. - Hide integration details behind a single options object so app code stays clean. Plugins are for one app. A module is for many apps and should install with zero or minimal manual wiring. ## Build a Nuxt module step by step ### 1) Scaffold the module Use the official starter. It includes TypeScript, unbuild, and a ready playground. ``` ``` You get `src/module.ts` for the entry, a `runtime/` folder for code that runs inside the host app, and a `playground/` Nuxt app for local testing. ### 2) Define metadata and options Give the module a name, a config key shown in `nuxt.config.ts`, and sensible defaults. Use `defineNuxtModule` from `@nuxt/kit`. ``` ``` This makes your module configurable via `awesome: { ... }` in a host app’s `nuxt.config.ts`. ### 3) Add runtime code: plugin, composable, and handler Runtime code lives under `runtime/`. Keep the public API small and stable. ``` ``` ``` ``` ``` ``` For client-only or server-only behavior, create `plugin.client` or `plugin.server` files and register the right one. ### 4) Expose components or server routes If your feature ships UI or extra routes, place them in `runtime/components` or `runtime/server` and register as needed. ``` ``` Prefer small, focused components and keep their props stable since host apps may rely on them across versions. ### 5) Use it in the playground The scaffold includes a `playground/` app wired to the local module. Run both together. ``` ``` ``` ``` Create a page and call your composable. ``` ``` If the playground seems stuck on an old build, restart it or run `pnpm -r dev` again so changes in `src/` rebuild. ### 6) Add types and DX polish Type your injections so host apps get IntelliSense. Also export your options type. ``` ``` Point `types` to the built declarations and publish only the build output. Consider an exports map so consumers cannot import sources by accident. ``` ``` If your runtime ships CSS, either import it from the host app or set a narrow `sideEffects` array so tree-shaking does not drop needed styles. ### 7) Package and publish Build, version, and publish to npm. Write a README with install, options, examples, and a changelog link. ``` ``` Test installation in a fresh Nuxt app created with `npx nuxi init`. Verify that `module options → runtimeConfig` works, server handlers mount, and your types resolve in the editor. ## Where modules fit in SaaS and AI projects For a SaaS, a module is the right place to package shared concerns across properties. Examples: - Billing and entitlements: wrap your payment provider client, expose helpers like `usePlan()` and `hasFeature('x')`, and register a secure webhook route. - Auth glue: auto-register a plugin that syncs session state to a composable, and add route rules for protected pages. - i18n defaults: ship a locale detector, default messages, and a directive for number and date formatting. - Marketing baseline: add analytics, SEO helpers, and consistent components like `` and ``. If you want to ship fast, pair your module with a Nuxt SaaS starter kit or a Nuxt boilerplate that already includes authentication, protected routes, an admin area, payments and checkout, i18n, transactional emails, analytics, SEO tools, cron jobs, and a landing page. Your module can focus on domain logic while the base handles foundation work. Building an AI tool for the web follows the same pattern. Wrap your model provider and configuration in a module. Expose a composable like `useAiClient()` with methods for chat, text, and image generation. Support switching models or providers with a single option. Keep pricing, trials, and usage metering in the app or backend, while the module handles the client, types, and error normalization. Early feedback helps shape the roadmap. You can wire in a feedback widget via a tiny plugin inside your module. Feedjolt is a good example of the kind of tool you might integrate to capture votes and rank requests while you iterate. When you buy a Nuxt boilerplate or a Vue Nuxt starter template for a new app, keep your own feature logic inside a module. That lets you swap the base later without a rewrite and keep the same composables and components across products. ## Common pitfalls and fixes - **Missing transpile for runtime.** If host apps error on syntax or imports, add `nuxt.options.build.transpile.push(resolver.resolve('runtime'))` in `setup`. - **Options not available at runtime.** Mirror module options into `runtimeConfig.public`. Read them with `useRuntimeConfig` in your plugin and composables. - **Wrong import paths after publish.** Publish only built files. Set `files: ["dist"]` and add an `exports` map to block deep imports into `src/`. - **Plugins run in the wrong environment.** Use `plugin.client` or `plugin.server` filenames, or guard logic with `process.client`/`process.server`. - **Playground uses a cached build.** Restart the playground or run `pnpm -r dev` so changes in `src/` rebuild the module. - **Global types not picked up.** Ensure your `dist/types.d.ts` is shipped and referenced by `types` in `package.json`. If you generate multiple d.ts files, re-export them from a single entry. - **Bundled dependencies break the host app.** Keep framework and Nuxt as peer dependencies. Do not bundle Vue or Nuxt types into your dist. - **Server routes collide.** Prefix your routes, for example `/awesome/*`, to avoid conflicts in host apps. ## Key takeaways - A Nuxt module packages reusable setup for many apps: plugins, composables, components, routes, and build config. - Scaffold with `nuxi`, define options with `defineNuxtModule`, and add runtime code under `runtime/`. - Test in a playground before publishing so you catch path, transpile, and runtime config issues early. - For SaaS and AI work, keep domain features in a module and let a Nuxt starter kit handle auth, payments, admin, analytics, and SEO so you ship fast. ## FAQ ### What is the difference between a Nuxt plugin and a Nuxt module? A plugin runs in one app and sets up runtime behavior. A module runs at build time and can add plugins, composables, components, server routes, and tweak build config across many apps. ### How do I test a Nuxt module locally before publishing? Use the scaffolded playground app, point it at your module’s local entry, and run a workspace dev script so the module rebuilds when you edit code. ### Can I make parts of my module client-only or server-only? Yes. Use separate plugin files like plugin.client.ts or plugin.server.ts, or guard code with process.client and process.server checks. ### How should I expose configuration from my module at runtime? Mirror options into runtimeConfig.public (or private) during setup, then read them from useRuntimeConfig in your plugin and composables. ### What Node and Nuxt versions should my module support? Target the current LTS version of Node and add a Nuxt peerDependency such as ^3.x. Test in a fresh Nuxt app to confirm compatibility. # How to Build a SaaS with AI Coding Agents – Step-by-Step Building a SaaS used to be a lonely, month-long slog. You were the designer, the coder, and the QA team. In 2026, that’s no longer the case. You can now build with a team of AI agents that handle the heavy lifting while you act as the architect. But there's a catch: AI is only as good as the foundation you give it. If your code is a mess, the AI will just make it a faster mess. Here is the exact workflow I use to leverage AI agents and a solid Nuxt foundation to launch products in days, not months. --- ## What Are AI Coding Agents? Unlike standard autocomplete tools, **autonomous coding agents** can understand your entire project. They can read your documentation, find bugs across multiple files, and write complex logic based on a simple sentence. Why founders are switching to an AI-first workflow: - **10x Speed:** You spend seconds describing a feature instead of hours coding it. - **Lower Barrier to Entry:** You don't need a Computer Science degree to build a professional app. - **Instant Debugging:** AI finds and fixes errors before you even notice them. To get the most out of these **AI coding assistants for SaaS**, you need a structured foundation. This is where [ShipAhead](https://shipahe.ad){rel=""nofollow""} comes in. --- ## Step 1: Establish a Clean Foundation AI tools work best when they aren't guessing. If your code is messy, the AI will produce messy results. By starting with a professional boilerplate, you give the AI a "clean map" to follow. [ShipAhead](https://shipahe.ad){rel=""nofollow""} provides: - A standardized Nuxt 4 and Tailwind CSS setup. - Clear naming conventions for database tables and API routes. - An architecture optimized for **accelerate SaaS development**. **Pro Tip:** Your first step should be installing your boilerplate. This ensures that every line of code the AI writes follows a proven, scalable pattern. --- ## Step 2: Optimize Your AI Workflow To **build a SaaS fast with AI**, you need the right tools. We recommend using **Cursor** combined with **Claude 3.5 Sonnet** (or the latest model). 1. **Index Your Project:** Let Cursor scan your files so it knows exactly how your auth and database work. 2. **Use a Developer Log:** Create an `AGENT.md` file. List your technical choices, your preferred styling rules, and how you handle state. 3. **Reference Your Docs:** If you are using a specific library, provide the AI with the documentation URL. --- ## Step 3: Writing Productive Prompts The secret to building with AI isn't just "asking." It is about providing context. Instead of saying "Build a dashboard," try being specific. **Example Prompt:** > "Using our existing UI library, create a new 'Team' page. Include a list of members from the 'users' table, a button to invite new members via email, and a toggle to change their role between 'Admin' and 'Member'." Because you are using a structured foundation, the AI knows exactly where the users are stored and how the buttons should look. --- ## Step 4: The Human-in-the-Loop Review The AI is your assistant, not your replacement. You must still be the architect. - **Review Every Commit:** Always look at what the AI changed. - **Run Local Tests:** Ensure the new feature hasn't broken the login flow or payment system. - **Iterate:** If the styling is off, simply ask the AI to "Make the buttons more rounded like the home page." --- ## Step 5: Launching and Scaling Once the AI has helped you build your core features, use it to help you go live. Ask it to: - "Generate a Sitemap for my Nuxt app." - "Write the meta descriptions for my blog posts." - "Help me configure the environment variables for Vercel." --- ## The Future of Shipping The "solo founder" is more powerful than ever. By using **Build SaaS with AI agents**, you can compete with companies that have 10x your budget. Stop waiting for a co-founder or a bigger budget. Start with [ShipAhead](https://shipahe.ad){rel=""nofollow""}, fire up your AI assistant, and build your business today. # How to Build and Sell an AI Tool Online in 2026 It feels like everyone is building an AI tool these days. If you’ve been scrolling through X wondering, *"How do I actually build and sell one of these myself?"* you're in the right place. The good news? In 2026, the technical barriers are basically gone. You don’t need a PhD in machine learning or a server farm to build something people will pay for. All you need is a specific problem, an API, and a stack that doesn't get in your way. Here is the exact blueprint I use to go from idea to first sale. --- ## Step 1: Finding Your Niche We've all seen a million generic "ChatGPT wrappers." Don't build the million-and-first. If you want to make a dent, you have to get hyper-specific. - **Solve a super specific workflow:** "An AI blog writer" is too broad. But "An AI report generator for freelance home inspectors"? Now you're talking. - **Bring your own data:** AI is basically magic when you hook it up to unique data. Find a weird proprietary API and feed that context into the LLM. - **Nail the UX:** Sometimes, people aren't paying for the AI; they are paying because you made the AI actually easy and pleasant to use. Never underestimate a beautiful interface. --- ## Step 2: Picking Your Brain (The API) You don’t have to reinvent the wheel. Just pick the off-the-shelf brain that fits your app best. 1. **Anthropic (Claude):** If your tool involves deep reading, nuanced writing, or coding, Claude 3.5 Sonnet is honestly incredible. 2. **OpenAI:** The old reliable. GPT-4o is fast, solid, and everyone trusts it. 3. **OpenRouter:** Can’t decide? Don't! OpenRouter gives you one single API key that lets you seamlessly switch between Llama, Anthropic, and OpenAI on the fly. --- ## Step 3: Skipping the Boring Stuff When inspiration strikes, the last thing you want is to spend two weeks messing around with auth tokens and database schemas. Your energy should go into the feature that actually makes you money. This is exactly why so many indie hackers use boilerplates. A setup like **ShipAhead** gives you the entire Nuxt foundation ready to go on day one. It hands you: - **Authentication:** Login logic is already handled. - **Stripe Payments:** Ready to take people's money. - **Database (Drizzle ORM):** Ready to save your users' data without the headache. By letting a boilerplate handle the plumbing, you can jump straight into building the cool AI features that set your product apart. --- ## Step 4: Making Money (Setting Up Payments) How do you actually plan to charge people? - **SaaS Subscriptions:** The holy grail. A flat monthly fee for a set amount of usage. - **Pay-As-You-Go:** Buying credits works great if your API costs are unpredictable. - **Lifetime Deals:** A sweet one-time payment. It brings in fast cash early on but be careful—supporting users forever is a long time. Stripe makes all of this a breeze. (And yes, if you grabbed a boilerplate earlier, Stripe is usually already wired up for you). --- ## Step 5: Getting Those Sweet, Sweet First Users Alright, the app is live. Now you have to convince strangers to try it. - **Build in Public:** Share the messy behind-the-scenes on X or LinkedIn. People love an underdog story. If you want to put this on autopilot, a tool like [LiFast](https://lifa.st){rel=""nofollow""} is awesome for scaling your LinkedIn B2B outreach without spending all day on it. - **Tap into Reddit:** Subreddits are goldmines for early users complaining about the exact thing your app fixes. Instead of manually digging through posts all day, [MediaFast](https://mediafa.st/?atp=5lU9lT){rel=""nofollow""} can automatically find those keyword mentions for you, so you can join the conversation naturally. - **Launch on Product Hunt:** A classic right of passage. A good launch day can easily scoop up your first hundred paying users and secure some solid backlinks. - **Treat Early Users Like Gold:** Once they sign up, you *have* to listen to them. Dropping a quick widget onto your site lets you handle support and feature requests instantly, proving to your users that a real human is listening. - **Play the SEO Game:** Start churning out targeted blog posts so Google starts doing the heavy lifting for you over time. ## Wrapping Up Getting an AI tool off the ground in 2026 is honestly a blast. Start small, talk to people to make sure they actually want it, plug into OpenRouter, and skip the boring dev work with a boilerplate like ShipAhead. It's time to stop wondering *"how do I build and sell an AI tool online?"* and start actually building the thing. # Build and Sell an AI Tool with Nuxt, Step by Step ![Build and sell an AI tool with Nuxt. A SaaS starter kit gives you auth, payments, chat, i18n, SEO, analytics, and fast deploys so you can start charging.](https://shipahe.ad/images/blog/how-to-build-and-sell-an-ai-tool-online-with-nuxt-step-by-step/post-788.webp){style="max-width:100%;border-radius:12px"} You have an idea for an AI app, but every path to launch detours into auth, billing, dashboards, i18n, and deployment. If you are asking “How do I build and sell an AI tool online,” the shortest route is to cut the plumbing work and focus on the job your tool improves. A Nuxt SaaS starter kit removes the slow parts so you can test pricing and start charging sooner. ## Choose one narrow use case and match the model Ideas that gain traction solve a specific, costly task. Pick one weekly job your user already does, then make it faster or more consistent. Examples: a marketing brief generator for franchise locations, an email rewrite assistant for recruiters with tone presets, or an image idea board that outputs cohesive product photo prompts for craft sellers. Specific beats general because outcomes are measurable and you can price on them. ### Define the narrow workflow - Inputs. Text, a URL, CSV, or image. Name exact fields and formats. Example: CSV with columns job\_title, years\_experience, location. - Output. A single paragraph, structured JSON, a gallery of 4 images, or a downloadable file. Provide a sample output in your UI so users see the finish line. - Constraints. Word count, brand voice, file size, image dimensions, privacy. Fail fast when inputs do not meet rules. - Evaluation. Define a success check. Example: JSON must include fields A, B, C and pass a schema validator. Images must be at least 1024×1024. Start simple. Ship one primary task and a single variation. The Nuxt boilerplate from shipahe.ad includes AI chat, text generation, and image generation with switchable GPT models. You can try model and temperature settings without rebuilding the UI every time. ### Decide what to store and for how long - Persist prompts and outputs if users revisit work. Use the preconfigured ORM and add tables like generations and conversations with user\_id, type, payload, result, tokens\_used, created\_at. - Use S3-compatible storage for uploads and generated files. Set an automatic cleanup after N days for free plans. - Skip storage for throwaway tests to save cost. Make this explicit in the UI so users know what is kept. - PII. If your use case does not need it, drop names, emails, and IDs at the edge. Log only what you need to debug. ## Build the core experience in Nuxt Use a Nuxt SaaS boilerplate to wire the flow fast and keep it consistent. ### Auth and protected routes - Gate the app with middleware so only signed-in users access tool pages. The kit includes email and password, magic links, Google login, and password resets. - Place paid features under /app with server checks on every API call. Never rely on client flags to enforce limits. ### Implement the core UI - Chat assistant. Drop in the chat component, set a clear system prompt, and bind to your chosen model. Stream tokens to the UI for fast feedback. Save each exchange so users can resume threads. - One-shot generator. Create a simple form that posts to a server route like /api/generate and returns a structured result. Show a skeleton state and a clear success format users can copy or download. - Image ideas. Use the image generation helper. Limit to a fixed number of images per run and store generated URLs in S3-compatible storage. Add a “save to board” action that writes to the database. ### Server logic, guardrails, and deployment - API routes. Use Nitro server routes in /server/api. Validate input, call the model, and return typed results. Prefer POST for generations and include an idempotency key to prevent double-charges on retries. - Rate limiting. Before each request, read the user’s plan and usage. Keep a usage table with counters per feature and a period\_start. Block overages and return a clear upgrade path. - Token budgets. Track tokens\_used per run. Cap requests by count and by token budget so power users do not surprise you on cost. - Safety. Sanitize inputs, strip disallowed HTML, and reject unsupported file types. Log errors in the admin panel with the request\_id for quick triage. - Emails. Use the built-in transactional templates for welcomes, resets, and receipts. Schedule a day-two onboarding tip email with a background job. - Env and deploy. Ship with environment variables for model keys, database URL, storage, and SMTP. The boilerplate supports Vercel and similar hosts with SSR, edge caches, and health checks already set up. ## Price plans and wire subscriptions Map price to value. In most AI tools, value comes from the number of generations, task complexity, or access to advanced models. Keep it simple at launch and let usage data guide you. ### Practical starting plans - Free. Limited runs per day and basic models. - Starter, $9 to $19. Higher limits, saved history, and image generation access. - Pro, $29 to $49. Priority limits, bulk tasks, and higher caps. Use the payment processing in the Nuxt SaaS starter kit to add checkout for one-time and subscription payments. The system supports multiple swappable providers, so you are not locked in. Gate protected pages and API routes by plan tier in the database. If a user downgrades or cancels, the next request should read the current plan and adjust access immediately. ### Lifecycle, limits, and receipts - Trials. Offer a short trial of the Starter plan. Send reminders three and one days before trial end with scheduled jobs. - Overages. Show a friendly cap message and a one-click upgrade link. If you allow pay-as-you-go, show an estimate before confirming the extra run. - Limits by weight. Assign weights to actions. Example: text run = 1 unit, image run = 3 units, bulk run = 5 units. This keeps pricing predictable. - Receipts and taxes. Send PDF receipts and collect tax details at checkout. Store invoices for audit in your database and storage bucket. ## Launch a landing page that converts and can be found Your first users will judge you by the landing page and the first minute in the app. Use the prebuilt landing page in the starter kit and swap copy to match your use case. Add a small pricing table, a demo GIF or short video, and a signup button that goes straight to auth. Ship the same day. ### Make it discoverable and fast - SEO automation. The kit generates meta tags, Open Graph images, and a sitemap. Focus on headlines, proof, and internal links. Add a simple help article and a use-case post with Nuxt Content. - Languages. If your audience is global, turn on the language switch and add a second locale for the homepage and pricing. Translate only the surfaces that affect conversion first. - Schema and basics. Add Product and FAQ schema to the landing page if applicable. Use canonical URLs, a clean robots.txt, and noindex for app dashboards. - Speed. Compress images, lazy-load non-critical scripts, and use the built-in image component. Aim for a sub 2-second LCP on mobile. If you want outside help on layout, performance, or conversion, [a website design company](https://redstudio.ie){rel=""dofollow""} that builds and optimizes business websites and e-commerce stores can refine your layout and tune on-page SEO so more visitors turn into trials. ## Measure usage and iterate weekly Once traffic arrives, decisions should come from behavior, not guesses. The Nuxt SaaS template includes analytics for pageviews, signups, and user flows. Pair that with database events to see which features lead to upgrades. ### What to watch in week one - Signup to first output. Minutes from account creation to the first successful generation. - Activation threshold. The number of runs in 48 hours that correlates with upgrades. Nudge users to that number with a checklist. - Cap hits. How often users hit plan limits. This informs both pricing and rate limits. Instrument key events like generation\_started, generation\_succeeded, generation\_failed, upgrade\_clicked, and checkout\_completed. Send a daily email report with counts of signups, activations, generations, errors, and cancellations. If a cohort stalls on the prompt form, reduce required inputs and add one good example prompt. If Pro users generate more images than text, move quota weight accordingly. ### Common pitfalls to avoid - Building too much before billing. Add subscriptions on day one. Your best feedback is paid. - Vague outputs. Define success formats. Return clean text or validated JSON the user can copy or download. - Loose access control. Protect all generation routes and check plan limits on every request. - Silent failures. Show a clear error state and log it with context in the admin area. - No follow-up. Use transactional emails to bring new users back for a second session. With a Vue Nuxt starter template, you avoid weeks of setup. The shipahe.ad Nuxt SaaS boilerplate includes user authentication with protected pages, payments for one-time and subscription plans, AI chat and generation with switchable GPT models, a preconfigured database with an ORM, S3-compatible file storage, transactional emails, an admin panel, scheduled cron jobs, a blog with Nuxt Content, built-in analytics, i18n, SEO automation, and a prebuilt landing page you can customize. If you would rather buy a Nuxt boilerplate than stitch pieces together, this is a direct path to shipping and charging. ### Key takeaways - Pick one high-value task and define inputs, outputs, constraints, and a success check. - Use protected pages, server checks, and streaming to make it feel real on day one. - Wire subscriptions early and gate usage by plan with a simple usage table. - Launch with the prebuilt landing page, SEO automation, and two useful blog posts. - Track activation metrics, send daily summaries, and iterate weekly based on data. ## FAQ ### How fast can I launch an AI app with a Nuxt starter kit? You can ship a basic paid MVP in a few days. Auth, payments, AI chat and generation, analytics, and a landing page are already in place, so you mainly add your prompts and UI. ### Do I need to build my own billing system? No. The kit includes checkout flows for one-time or subscription payments and supports multiple providers. You map plan limits to your routes and database. ### Can I support multiple languages at launch? Yes. The starter includes multi-language support with an in-app language switch, so you can localize the homepage and pricing without extra tooling. ### What data should I store from user generations? Store enough to be useful later, like prompts, outputs, and timestamps. Use S3-compatible storage for files. Skip storage for throwaway tests to control cost. ### How do I keep abuse and spam under control? Use protected pages, check plan limits on every request, and monitor activity in the admin panel. Ban obvious spammers and add rate limits per plan. ## Recommended resources - [a website design company](https://redstudio.ie) # How to Find Profitable SaaS Ideas in 2026 – A Complete Guide The biggest mistake founders make is building in a vacuum. You spend six months perfecting an app only to realize that nobody actually wants to pay for it. I've learned the hard way: You don't need a "revolutionary" idea to build a profitable SaaS. You just need to solve a real, annoying problem for a specific group of people. Forget the "shower thoughts." Here is the tactical framework I use to find niches with high demand and low competition—and how to validate them before you write a single line of code. --- ## The Rule of Profitable Ideas A great SaaS idea isn't a "shower thought." It is a solution to a recurring headache. If people are already complaining about a problem, they are likely willing to pay to make it go away. When searching for **B2B SaaS ideas**, look for tasks that are: - **Repetitive:** Something people have to do every day. - **Slow:** Something that takes hours but should take minutes. - **Expensive:** Something that requires hiring an expert or a large team. --- ## 4 Simple Ways to Discover Your SaaS Niche ### 1. The "Scratch Your Own Itch" Method Think about your own workday. What tools do you use that are slow, ugly, or frustrating? If you are a developer, a marketer, or a lawyer, there is likely a **low competition SaaS** niche hiding in your daily workflow. ### 2. Look for "AI-Native" Replacements Many established tools were built 10 years ago. They are bloated and weren't designed for AI. Can you build an AI-first version of an existing tool that is 10x faster? This is a massive opportunity for **SaaS niche discovery**. ### 3. Mine the "Complaint Departments" Go where people are unhappy. Sites like Reddit, X (Twitter), and G2 are gold mines. Search for: - "I hate it when [Software Name]..." - "Why is there no app to..." - "How do I do X without using [Expensive Tool] ?" ### 4. Shadow a Non-Tech Business Owner Talk to a plumber, a restaurant owner, or a real estate agent. Ask them: "What is the most boring part of your week?" They aren't looking for "cutting-edge tech"; they are looking for a way to save two hours on their Saturday. --- ## How to Validate Your SaaS Concepts Before you touch your keyboard, you must **validate your SaaS concepts**. Validation means getting evidence, not just "opinions." - **Step 1: The Search Test.** Use Google Keyword Planner to see if people are actually searching for terms related to your problem. - **Step 2: The Landing Page Test.** Build a simple page using your [starter kit](https://shipahe.ad){rel=""nofollow""} and see if people will give you their email to hear about the launch. - **Step 3: The Pre-Sale Test.** Can you get 5 strangers to pay you $50 for a lifetime deal or a beta access? If they pay before the app exists, you have a winner. --- ## Stuck? Use Our Free Idea Generator If you are still looking for inspiration, we created a tool just for you. Our [AI SaaS Idea Generator](https://shipahe.ad/ai-saas-idea-generator){rel=""nofollow""} analyzes current market trends to suggest **profitable SaaS ideas for 2026** tailored to your skills. --- ## From Concept to Launch in Days Finding the idea is the hard part. The coding shouldn't be. Once you've identified your niche, don't spend months on the setup. Use [ShipAhead](https://shipahe.ad){rel=""nofollow""} to get your core features live. It handles the logins, the payments, and the database, so you can focus 100% on the unique part of your idea. --- ## Final Thoughts Great ideas are everywhere. The difference between a "wantrepreneur" and a founder is execution. Find a problem, validate it, and start shipping. Ready to build? Grab [ShipAhead](https://shipahe.ad){rel=""nofollow""} and turn your idea into a real business today. # How Much Time Does a Nuxt Starter Kit Actually Save? The biggest question I get from developers isn't "how do I build this?" It's "**is this still worth the effort?**" In 2026, the SaaS market is crowded. But the math has changed. The reason most projects fail isn't a lack of features—it's a lack of speed. If you spend three months building the foundation, you've already lost to the founder who launched in three days. ### The Real ROI of Speed Let's look at the numbers. This is the difference between building your foundation from scratch versus using a professional [Nuxt starter kit](https://shipahe.ad){rel=""nofollow""}. | Feature | Building From Scratch | Using a Boilerplate | Time Saved | | :-------------------- | :-------------------- | :------------------ | :-------------- | | **Authentication** | 15-20 Hours | < 5 Minutes | \~18 Hours | | **Stripe Billing** | 20-30 Hours | 10 Minutes | \~25 Hours | | **Admin Dashboard** | 40+ Hours | 0 Minutes | \~40 Hours | | **SEO & Meta Tags** | 10 Hours | 0 Minutes | \~10 Hours | | **Total Launch Time** | **3-6 Weeks** | **< 48 Hours** | **\~90+ Hours** | When you realize a boilerplate saves you **90+ hours of development**, the question changes from "is SaaS worth it?" to "**how fast can I ship?**" --- ## Why the SaaS Business Model is Still King To understand the **future of SaaS business**, we have to look at how much the barrier to entry has dropped. | Feature | The Old Way (Pre-2023) | The 2026 Way | | :------------------- | :------------------------ | :------------------------------ | | **Development Time** | 3-6 Months | 3-7 Days | | **Setup Cost** | Thousands in dev hours | A few hundred for a boilerplate | | **Team Size** | 2-3 Developers | 1 Indie Hacker + AI Agents | | **Maintenance** | Complex server management | Serverless & Auto-scaling | Because it is so much cheaper and faster to launch, the risk of **starting a SaaS today** is a fraction of what it used to be. --- ## Why the SaaS Business Model is Still King Software as a Service remains the best business model ever created for one reason: **Recurring Revenue.** Unlike selling a physical product or a one-time service, a SaaS provides: - **Predictable Cash Flow:** You know exactly how much you're making next month. - **High Profit Margins:** Once the software is built, the cost of adding a new user is nearly zero. - **Asset Value:** A profitable SaaS with stable churn can be sold for 3x–5x its yearly profit. --- ## 3 Pillars of a Successful Indie Hacker SaaS in 2026 If you want to succeed, you need a different strategy than the VC-backed giants. ### 1. Solve a "Vertical" Problem Don't try to be "Slack for everyone." Be "The communication tool for boutique dental clinics." When you narrow your focus, your marketing becomes cheaper and your users become more loyal. ### 2. Prioritize Time-to-Market In 2026, speed is a feature. If you spend three months building in secret, a competitor will launch in three days using a [starter kit](https://shipahe.ad){rel=""nofollow""} and steal your users. Use [ShipAhead](https://shipahe.ad){rel=""nofollow""} to handle the infrastructure so you can go live while the idea is fresh. ### 3. Build an "AI-First" Experience Don't just add an AI chatbot to a legacy app. Build your SaaS around an AI workflow that saves your users hours of manual work. That is where the real value lies in the **SaaS market trends** of today. --- ## SaaS Profitability Analysis: Can You Still Win? Let's look at the numbers. If you solve a problem that saves a business $500 a month, charging them $50 is an easy sell. - **Cost of Goods Sold (COGS):** With serverless hosting and modern databases, your monthly cost per user is pennies. - **Customer Lifetime Value (LTV):** If a user stays for 24 months at $50/mo, that's $1,200 from a single customer. The math for a solo founder remains incredibly attractive. --- ## The Verdict Is building a SaaS worth it? Absolutely. But only if you stop acting like a 2015 startup. Don't over-engineer. Don't hire a team. Don't build your own login system. Grab [ShipAhead](https://shipahe.ad){rel=""nofollow""}, leverage AI, and build a business that serves a real niche. The opportunity has never been bigger for those who ship fast. # Nuxt 3 authentication with email, magic links, and Google ![Set up Nuxt 3 auth with email/password, magic links, and Google. Secure sessions, protect routes, and ship faster with a production-ready starter.](https://shipahe.ad/images/blog/nuxt-authentication-with-email-magic-links-and-google/post-479.webp){style="max-width:100%;border-radius:12px"} Authentication is the first real test for a Nuxt app. You need email and password for confidence, magic links for a low-friction first session, and Google for one-tap sign in. You also need clean redirects, protected routes, and sessions that do not break under real traffic. This is the playbook I use when building SaaS and AI tools with Nuxt 3 and what Shipahe.ad ships out of the box so you can make your first dollars online without burning weeks on plumbing. ## Plan the flows before you code Decide exactly how users enter and recover access. Map these paths: - Sign up: fields collected, welcome email, post-signup redirect. Keep it to email and password. Add name later in onboarding. - Sign in: email + password, magic link, and Google as distinct, obvious choices. Always fall back to email-only recovery. - Password reset: request page, token lifetime, confirmation page, and whether you auto sign in after a successful reset. List your emails and the triggers: welcome, verification if required, magic link, reset request, and reset success. Write the subject lines now so you avoid vague defaults later. For multi-locale apps, draft both the UI copy and emails per locale so your i18n is consistent from day one. ## Email/password and magic links that feel fast and safe Email/password is your baseline. Magic links remove friction for first-time users and demos. Both should land on the same account. 1. **Pages and UX.** Use three pages: /signup, /login, /reset. Keep forms short. On magic link submit, swap the form for a clear “Check your email” state and show which address you sent to. For all auth actions, show definitive success and failure states. 2. **Server-side hashing and validation.** Hash with Argon2id on the server. Enforce a minimum length and check common passwords with a local entropy check such as zxcvbn. For breach checks, hit the Have I Been Pwned k-anonymity API server side. Rate limit by IP and user ID. 3. **Password reset with short-lived tokens.** Generate a random token, store a hashed version with user ID, purpose, and an expires\_at no longer than 15 minutes. Send a link to a page that verifies and consumes the token once. On success, invalidate the token and clear other active sessions for that user. 4. **Magic link issuance and redemption.** Create a single-use token bound to email and an expiry of 10–15 minutes. Include a jti so you can revoke the exact token on redemption. Consider adding a fallback 6–8 digit code in the email for copy-paste. 5. **Email deliverability that actually lands.** Authenticate your domain with SPF, DKIM, and DMARC. Use a dedicated subdomain for transactional mail, like mail.yourapp.com. Include the expiration time and the requester IP in the email so users can spot suspicious activity. Minimal Nuxt server handlers for login and sessions could look like this: ``` ``` In Shipahe.ad, email/password, reset, and magic links are already wired with templates, rate limits, and a single account per email. You focus on copy, not the edge cases. ## Google sign-in without duplicate accounts Google reduces friction for users on Chrome and Android. Keep it tight and link to existing accounts instead of creating clones. 1. **Create OAuth credentials.** In Google Cloud Console, add an OAuth client with your local and production redirect URIs. Scopes openid email profile are enough for sign-in. Use a strict Authorized JavaScript origins list. 2. **Defend the callback.** Verify state for CSRF and nonce for replay. Validate the ID token with Google’s certs and check aud, iss, and exp. Extract the *verified* email only. 3. **Link by email, not by provider ID alone.** If a user with the same verified email exists, attach the Google provider to that user. Only create a new user when there is no match. Store provider name and provider user ID. Keep refresh tokens only if you call Google APIs later, and encrypt them at rest. Shipahe.ad includes Google as a toggle. The callback handler already verifies state and nonce and links to an existing account by email to avoid duplicates. ## Protect routes and manage sessions on both sides Client checks improve UX. Server checks provide security. Use both. 1. **Client route guards.** Add route middleware for gated pages. Redirect anonymous users to /login and redirect authenticated users away from onboarding or auth pages when appropriate. ``` ``` 2. **Server enforcement.** Never trust the client. Wrap server routes with a session check and role check. ``` ``` :br 3. **Cookie strategy.** Put session IDs and refresh tokens in httpOnly, Secure cookies. Use SameSite=Lax for most apps. If you serve the app and API across different domains, use SameSite=None and Secure on HTTPS only. Do not store tokens in localStorage. 4. **Short access, longer refresh, rotate often.** Keep access tokens short lived. Rotate refresh tokens on every use and revoke the previous one to kill replay. On logout, delete cookies and revoke refresh tokens, and broadcast a logout event across tabs with the Storage API. 5. **CSRF and state.** Protect state-changing POST routes with CSRF tokens. For OAuth, verify state and nonce every time. ### Common pitfalls - **Duplicate accounts.** Always link Google and magic-link sign-ins to the same user by verified email. - **Overlong magic links.** Keep tokens short lived and single use. Invalidate on redemption. - **Weak email deliverability.** Set SPF, DKIM, and DMARC. Use a transactional subdomain. Clear subjects beat clever ones. - **Client-only checks.** Guard server routes. Client redirects help UX, not security. - **Leaky storage.** Use httpOnly cookies. Avoid localStorage for secrets. - **No rate limits.** Throttle login, reset, and magic-link endpoints. ## Build faster with a Nuxt SaaS starter kit After sign-in works, the next drop-offs are onboarding and checkout. Send users to a crisp setup checklist, then a single checkout that supports one-time and subscriptions. Fire a receipt email that includes plan, amount, and a support contact. In practice, steady operations beat clever features. A good external example is this [operations guide to selling more on Mercado Libre](https://meliboost.com/blog/how-to/como-vender-mas-en-mercado-libre-tacticas-accionables/){rel=""dofollow""}, which shows how software centralizes orders, messages, inventory, and facturación CFDI Mercado Libre so teams stop guessing and start shipping orders. Same idea here. Tight systems around checkout, messaging, and receipts cut support tickets and churn. If you want a working base instead of a blank repo, Shipahe.ad is a Nuxt starter kit with production auth in place. You get: - User accounts with email/password, magic links, Google sign-in, password reset, and route protection already wired. - Transactional email templates with i18n so your login and receipt messages match the user’s locale. - An admin dashboard to view users, set roles, and ban obvious spammers. - Checkout flows for one-time and subscriptions with swappable providers like Stripe or Paddle, plus webhooks and dunning hooks you can enable later. - Analytics for pageviews, signups, and key actions so you can spot friction without adding a second tool on day one. - SEO helpers for meta, Open Graph images, and sitemaps, and a landing page you can customize by editing copy. - Deployment presets for modern hosts and clean .env handling across local, staging, and production. It is designed to play nicely with AI coding tools like Cursor and Claude so small changes and repetitive edits stay quick while you focus on shipping your product. ### Key takeaways - Plan sign up, sign in, and recovery before writing code to avoid rework. - Implement email/password and magic links with the same account and add Google without creating duplicates. - Protect pages on the client and the server. Store sessions in httpOnly cookies and rotate refresh tokens. - Watch auth metrics and email deliverability so you catch configuration issues early. - A Nuxt boilerplate like Shipahe.ad lets you launch faster without rebuilding the basics. ## Recommended resources - [operations guide to selling more on Mercado Libre](https://meliboost.com) # Nuxt DevTools for SaaS: a focused workflow to ship faster ![Debug routes, state, and performance with Nuxt DevTools. A concrete workflow for SaaS teams, plus how a Nuxt boilerplate removes setup drag.](https://shipahe.ad/images/blog/nuxt-devtools-11-tips-to-speed-up-saas-development/post-828.webp){style="max-width:100%;border-radius:12px"} Nuxt DevTools turns your local app into a live control panel. You see routes, state, server handlers, and payloads as they change. If you ship SaaS with Nuxt or you are choosing a Nuxt boilerplate, using DevTools well is the fastest way to cut bugs and move features to done. This is the workflow we use while building and selling our own Nuxt SaaS starter kit. ## Turn on DevTools the right way Get DevTools running on day one and wire it to your environments so you do not guess later. - Enable it in nuxt.config.ts and disable it for production builds: ``` ``` - Open the in-app panel from the floating tab in development. Keep it visible while you code and during smoke tests. - Make runtime config obvious. Use public keys for client values and private keys for server handlers. Confirm them in DevTools before you push: ``` ``` - Keep environment parity tight. Point local builds to staging services when possible and verify in DevTools that auth callbacks, webhook URLs, and storage buckets match the environment you expect. This prevents the classic sandbox-in-prod mistake. - Make failures loud. Add an error boundary component for critical pages and reproduce errors with DevTools open so you can tie the stack trace to the exact component tree and runtime config that caused it. ## Prove your routes, APIs, and auth are correct Most launch delays in SaaS come from routing and auth mismatches. DevTools closes that gap. - Pages and middleware. In the routes panel, confirm the matched page, route params, layout, and middleware chain for each navigation. For protected areas, you should see your auth middleware fire on every visit. - Server routes. Open the server routes view and hit each handler you care about: signup, login, billing callbacks, file uploads. Watch the status codes and payload shapes. Fix missing params and wrong HTTP methods now, not after QA. - Redirects. Step through login, magic links, and OAuth sign-ins. In DevTools, confirm the redirect chain and check store flags that gate dashboards. You want to see 401 or 403 for anonymous users and a clean 200 for authorized users, with no flicker to a public route. - Webhooks and callbacks. Trigger a test payment or subscription event. While DevTools shows server routes, verify your webhook handler runs, updates user state, and that the UI reflects the change without a manual refresh. ## Follow state through critical flows When signup, onboarding, or checkout misbehaves, time-travel debugging beats print statements. - Pinia timeline. Open Vue Devtools from within Nuxt DevTools and watch actions and mutations as you click. Replay a flow, freeze a frame, and inspect the exact state your UI read before a bad branch. Name your actions well so the timeline reads like a story. - Form edges. Toggle slow network in your browser and observe loading flags, validation errors, and disabled states. Confirm your store does not drop tokens or double-submit on retries. - Plugins and load order. In the plugins list, verify where each plugin runs: client, server, or both. That tiny detail explains many “works SSR, breaks on client” bugs. - Typed errors. If your codebase is fully typed, DevTools inspection is faster because you know what a value can be. Throw domain-specific errors with a code and context. In DevTools you can see the code, the component where it surfaced, and the state that triggered it. - Prototype AI features. While you switch models or prompt shapes, keep DevTools open and watch request timing, token inputs, and UI state. You get instant feedback if a loading flag never resets or a streaming response appends out of order. ## Hunt real performance problems Avoid broad “optimize everything” work. Use DevTools to find the few things that matter. - SSR to hydration. Compare the server-rendered HTML with the hydrated tree. Hydration mismatch warnings and unnecessary reactive work show up fast. Remove non-deterministic code in setup and gate client-only behavior behind process.client checks. - Payloads. Inspect route payload size and timing. If first contentful paint is fine but time to interactive drags, you likely ship too much JS. Trim payload props you never read on the client and avoid serializing whole records when an ID will do. - Imports and bundles. In the imports graph, look for heavy libraries pulled into the client by a single import. Common wins: - Switch `import { format } from 'date-fns'` to `import format from 'date-fns/format'` to avoid tree-shaking issues. - Lazy-load editors, charts, and maps via `const Editor = defineAsyncComponent(() => import('...'))`. - Replace moment.js with a lighter alternative or server-side formatting. - Components that render too often. In the performance view, spot components that rerender on unrelated state changes. Move expensive computed logic server-side, memoize derived values, and use `v-once` for static UI. - Images. Serve responsive images and correct formats. If a page is fast locally but slow on mobile, you likely shipped a few oversized images or SVGs with needless detail. ## Build production features faster DevTools helps you validate the parts that make a SaaS feel complete: i18n, SEO, storage, jobs, and analytics. - i18n correctness. Switch locales in your app and watch params and state update. Confirm missing keys fall back cleanly and pluralization rules fire. If your routes include a `[lang]` segment, verify that navigation stays in-locale across guarded pages. - SEO while you code. Open the head inspector and check title, description, canonical, and og\:image. Ensure canonical URLs reflect route params and that titles match the current locale. Fixing this now prevents a post-launch sweep. - File storage. Upload, list, and fetch files while watching server routes and UI state. Confirm that signed URLs expire, access checks block cross-user reads, and progress bars track real upload status rather than guesses. - Scheduled jobs. Run job handlers locally with test inputs. While DevTools shows network calls and state, confirm the UI updates after the job runs. Users should see the effect of a report generation or reminder, not just a log line. - Analytics. If you track pageviews and signups, keep the events pane open while you click through routes. Verify a single, well-formed event per action. Double events often come from duplicated client-only plugins or hydration replays. ### Pair DevTools with a Nuxt SaaS starter kit If you want to buy a Nuxt boilerplate that already includes authentication, payments, an admin panel, analytics, and SEO defaults, a Nuxt SaaS starter kit like shipahe.ad removes setup work. It ships a fully typed codebase and SEO automation, which makes DevTools even more useful because you debug real features on day one. For founders asking “How do I build and sell an AI tool online,” its ready-made AI chat, text, and image generation plus payments mean you can ship fast and focus on your unique value. ### Wrap-up Nuxt DevTools shortens the path from “I think it works” to “I watched it work.” Keep it open, make small changes, validate in minutes, and commit. Pair it with a solid Nuxt starter and you get a straightforward route from idea to revenue. ### Key takeaways - Enable Nuxt DevTools early and wire it to your environments. - Use the routes and server panels to validate auth, APIs, and redirects. - Time-travel Pinia state to debug signup, onboarding, and checkout. - Find real performance wins in hydration, payloads, and imports. - Validate i18n, SEO, storage, jobs, and analytics while you build. ## FAQ ### What is Nuxt DevTools and why should I use it? Nuxt DevTools is a built-in developer toolbox for Nuxt 3 that lets you inspect routes, components, state, server routes, and performance. It speeds up debugging and iteration. ### How do I enable Nuxt DevTools? Enable it in your Nuxt configuration for development and open it from the overlay in your running app. Keep it off for production builds unless you know exactly why you need it. ### Can I use Nuxt DevTools with a SaaS starter kit? Yes. A Nuxt SaaS starter kit works seamlessly with DevTools, so you can inspect auth flows, payments, admin pages, i18n, and SEO defaults as you customize the app. ### How do I build and sell an AI tool online with Nuxt? Start with a Nuxt SaaS starter kit that includes AI chat and generation plus payments, then use DevTools to validate routes, state, and performance. Launch a simple paid plan and iterate. ### Does Nuxt DevTools help with performance? Yes. You can view timings, component updates, and payload sizes to find slow pages and heavy code paths. Trim assets or lazy load modules to improve speed. # Nuxt email templates: 7 examples for SaaS notifications ![Seven Nuxt email templates with subject lines, fields, i18n, cron, and deliverability tips. Ship reliable welcomes, receipts, trials, and more from day one.](https://shipahe.ad/images/blog/nuxt-email-templates-7-examples-for-saas-notifications/post-284.webp){style="max-width:100%;border-radius:12px"} Your SaaS earns trust every time an email lands on time, with the right details, and a clear next step. In Nuxt you can wire these messages to real product events and ship fast if you standardize your templates and data. Below are seven templates that cover the moments that matter, plus concrete Nuxt implementation notes for speed and reliability. ## Core transactional templates These messages confirm identity and set expectations. Keep them short, single purpose, and consistent across locales. - **Welcome**:br Goal: confirm the account and point to one action. Trigger on signup or first verified login. :br Subject ideas: "Welcome to \[Product] — your next step" or "You are in. Start with \[Feature]". :br Include: first name, account email, a single CTA to the dashboard or onboarding step, support link in the footer. :br Nuxt note: emit an auth event after user creation, enqueue an email job with the user locale, and render HTML from one template plus a text-only part. Set a short preheader like "Set up your first project in two minutes." - **Password reset**:br Goal: give a safe, time-boxed path to change credentials. :br Subject ideas: "Reset your \[Product] password". :br Include: a single reset button, link expiry window, and instructions if the request was not made by the user. :br Security: store a hashed, single-use token with a TTL. Invalidate on first use. Log IP and timestamp for audit. In Nuxt, route tokens to a protected page that checks validity on load and blocks form submission if expired. - **Account banned**:br Goal: communicate a decision and reduce back-and-forth. :br Subject ideas: "Your \[Product] account status". :br Include: decision summary, high-level reason mapped to policy, and a support contact if appeals are allowed. :br Safety: if access is fully revoked, do not link back into the app. If partial restrictions apply, link only to a read-only billing or export page. ## Billing and lifecycle emails Revenue-related messages must be precise and predictable. Standardize fields so your content stays the same even if you swap payment providers. - **Payment receipt**:br Goal: provide proof of payment with zero ambiguity. :br Subject ideas: "Receipt for \[Plan], \[Month] \[Year]". :br Include: plan or product, period or purchase date, last4 of card or payment method, subtotal, tax, total, currency, and a button to view the invoice. :br Nuxt note: define a provider-agnostic schema, for example { amount\_total, currency, tax\_amount, line\_items\[], invoice\_url, customer\_name }. Map Stripe or other provider payloads to this schema before rendering. Keep the layout simple with labels on the left and values on the right. Add a plain text footer clarifying that this serves as a tax invoice where applicable. - **Trial ending**:br Goal: make the next step obvious before access lapses. :br Subject ideas: "Your trial ends in 3 days" and on the final day "Your trial ends today". :br Timing: send 3 days before, on the day, and optionally 3 days after with a grace reminder. :br Include: days remaining, current plan, and two buttons side by side — Upgrade and Manage subscription. :br Scheduling: store trial\_end at signup. Use a scheduled task to query accounts where now is within the notice window, then enqueue messages by locale to avoid bursts. - **Failed payment**:br Goal: help customers fix billing without fear or confusion. :br Subject ideas: "We could not process your payment". :br Include: what failed, when the next retry occurs, and a direct button to update the payment method. :br Nuxt note: handle webhook events like invoice.payment\_failed, compute the next attempt time from the provider schedule, and send one email per invoice id. Use idempotency by storing the event id you processed to avoid duplicates. ## Product updates that drive adoption Feature announcements should be short, benefit led, and linked to a single action inside the app. Keep them out of transactional streams and respect preferences. - **Update or feature announcement**:br Goal: explain the value and let users try it in one click. :br Subject ideas: "New: faster filters for large projects" or "Save time with bulk actions in \[Product]". :br Include: a one-sentence benefit, a bulleted highlight of what changed, and one CTA that deep-links to the feature configured for the user role. Add a brief note on how to revert or find settings if relevant. :br Example context: hiring teams using [resume screening software](https://marxel.co){rel=""dofollow""} benefit from faster shortlist generation that reviews large batches of resumes against criteria and produces an explainable list for reviewers. Announce that improvement and link straight to the new filter setup with a signed, one-click deep link. :br Segmentation: send only to active users of related modules or plans. Suppress for users who have not logged in recently to avoid spam complaints, or include a "See what is new" digest instead. ## Localization, scheduling, and deliverability in Nuxt Design your emails so they scale across languages and time zones, arrive when they should, and clear spam filters. - **i18n structure**:br Use shared translation keys across all templates. Keep placeholders stable, for example: auth.reset.cta = "Reset your password" and billing.receipt.total = "Total: {amount}". Store locale with the user and pass it through your email queue so templates and date formatting are consistent. - **Date, time, and currency**:br Render with Intl.DateTimeFormat and Intl.NumberFormat so formats match user expectations. Respect local time zones in subject lines where space is tight, for example "Due on 12 Oct, 9:00". Use ISO timestamps in machine-readable attributes if you include structured data. - **Scheduling and retries**:br Set up a scheduler to send lifecycle notices at exact times. Use a daily job for trial reminders and a minute-level job for password resets or webhook-driven billing events. Implement exponential backoff for transient send failures and mark messages for manual review after the final retry. Persist a lightweight delivery log with email type, user id, locale, and provider message id so support can answer "did you send it" questions fast. - **Design and accessibility**:br Keep content width around 600 px, minimum 14 px body text, and clear contrast for buttons. Provide a text-only alternative part for every email. Write a 40 to 90 character preheader that complements the subject. Use descriptive button labels like "View invoice" instead of "Click here". Add alt text for logos and screenshots. Avoid images that contain critical text. - **Authentication and reputation**:br Authenticate your sending domain with SPF, DKIM, and DMARC before go-live. Use a consistent From name and a working Reply-To that routes to your support system. Warm up new domains gradually. For product updates, include a visible manage-preferences link and honor it. Keep link counts low in transactional messages. - **Templates and partials**:br Use a single header and footer partial across all templates so you can roll out branding changes once. Favor simple, table-based HTML or a compiled framework that outputs it. Test against light and dark mode in major clients. Snapshot tests on your render functions catch accidental copy changes before they ship. ## Key takeaways - Standardize seven essentials: welcome, reset, receipt, trial notices, failed payment, ban notice, and a focused product update. - Keep every email single purpose with one CTA and predictable fields so users act fast. - Drive sends from real events and schedules. Use webhooks for billing and daily jobs for trials. - Localize early with stable placeholders and format dates, times, and currency per user locale. - A Nuxt SaaS boilerplate with transactional templates, i18n, and scheduling lets you launch faster than hand-rolling from scratch. ## Recommended resources - [resume screening software](https://marxel.co) # Nuxt email templates: 7 transactional emails your SaaS needs ![Build trust and reduce churn with Nuxt email templates. Seven must-have transactional emails for SaaS, plus i18n, cron digests, receipts, and testing tips.](https://shipahe.ad/images/blog/nuxt-email-templates-7-transactional-emails-your-saas-needs/post-841.webp){style="max-width:100%;border-radius:12px"} Great products still churn if verification never arrives, receipts go missing, or a reset email lands too late. Treat transactional email as part of the product. Ship a tight, predictable set of Nuxt templates and you turn trust, activation, and recovery into defaults. If you plan to buy a Nuxt boilerplate or use a Nuxt SaaS starter kit, pick one that ships with working transactional templates, a language toggle, and scheduling. The Nuxt boilerplate on shipahe.ad includes pre-made transactional email templates, an in-app language switch for multi-language support, and cron jobs for automated summaries and reminders, so you can ship fast without duct tape. ## The seven transactional emails to ship first ### 1. Welcome and onboarding Set the tone, remove doubt, and point to one next step. Keep it short. Confirm the account and offer a single CTA like Connect your data or Create your first project. Include support contact and a link to your docs inside the app so users feel safe trying their first task. Implementation notes: add `{{ user.firstName }}` and `{{ subscription.planName }}`. Deep link to a signed route such as `/onboarding?step=2&token=...` so the user lands exactly where they should. If you are shipping an AI tool, include a small prompt they can paste for an instant win. ### 2. Verify email and magic links State what is happening, where the link goes, and when it expires. Make the button prominent and include a plain URL fallback. For Nuxt, generate the expiry server-side and store a one-time token with a short TTL, for example 15 minutes. If you support magic links, include device and approximate location to reduce confusion: *Sign in requested on Chrome from Paris, FR*. Close with a clear line on what to do if this was not them. ### 3. Password reset and security alerts Users want speed and certainty. Provide a Reset password button with a short expiry. When known, show the requester’s IP or device. Include a safe-out line: If you did not request this, no action is needed. Extend the pattern to security events: new device login, 2FA enabled or disabled, recovery codes generated, email address changed. Reuse a consistent header and footer across these templates so users recognize real messages and ignore spoofs. ### 4. Receipts and subscription updates Receipts reduce tickets and refund risk. Show product name, plan, billing period, subtotal, tax or VAT, currency, total, invoice number, and the last four digits of the card or payment method. Include legal business details where needed. Add a Manage subscription link that lands in your in-app billing page, not a bare provider portal, so context is preserved. For lifecycle updates, cover trials ending, renewals, payment failures, and successful recoveries. A simple dunning schedule works: failure at T+0 with update-payment CTA, reminder at T+3, final notice at T+7, then pause or downgrade at T+10. Keep copy calm and factual. ### 5. Usage summaries and reminders Show value without a login. A weekly or monthly digest should include activity highlights, credits or quota left, and a single recommendation. Put the snapshot up top and link to a deeper report in-app. If your product is an SEO assistant like RankGoat, summarize new backlinks found, posts published, pages fixed, and any alerts that need action. Only send when there is something to show or when a periodic checkpoint is due. For Nuxt, assemble data server-side, render a compact HTML template with conditional blocks, and throttle sends to protect deliverability. ### 6. Re-engagement and win-backs When usage drops, send a nudge that respects time. Show last active date, what they are missing, and one path back in. Offer to pause notifications, reduce frequency, or close the account so your list stays clean. Match win-backs to behavior. If a trial ended before setup, offer a guided call. If a core feature was used then abandoned, send a two-step checklist to create momentum again. Leave discounts as a last resort. ### 7. Trial and renewal reminders Remind users of key dates before they happen. Send a heads-up 3 days before trial end, on the day of conversion, and on renewal for annual plans. Include plan, next charge date, amount, and one CTA to change plan or billing info. This reduces surprise charges and chargebacks. ## Localization, design, and deliverability Localization is more than translating strings. Keep email copy as translatable keys and format dynamic values server-side so previews match what sends. Use ICU-style messages for plural rules and gendered languages. Store the user’s `locale`, `currency`, and `timeZone` and render dates like `2026-10-02 14:30` with the user’s zone. For currencies, format with the right symbol placement and thousands separators. For RTL languages, flip layout and alignment, not just text. Design for the lowest common denominator. Inline critical styles. Test a light and dark variant. Include a plain-text part that preserves intent. Add a preheader that completes the subject. Use real alt text for images or, better, avoid key copy in images. Keep width to about 600 px and keep buttons at least 44 px tall so they are tappable on mobile. Protect deliverability. Authenticate your domain with SPF, DKIM, and DMARC. Use a dedicated from address for transactional mail. Keep subjects honest: *Your receipt for Oct*, not clickbait. Throttle bulk summaries, avoid image-only layouts, and include a clear manage notifications link where appropriate. For security-critical emails, do not include an unsubscribe link, but do include how to reach support. ## Wire this into your Nuxt SaaS starter kit Start with a consistent HTML framework and partials for header, footer, and buttons. Store templates next to server routes so data mapping stays obvious, and expose a preview route in development so product and support can review copy without digging through code, for example `/dev/email?template=receipt&user=123`. Version templates with a `templateVersion` flag in the payload so you can resolve cache issues predictably. Trigger emails from a single source of truth. In a Nuxt boilerplate you will often have an auth module, a payments module, and background jobs. Wire templates to events from each: - Auth events: sign up, email verified, password reset requested, new device login, 2FA toggled. - Payment webhooks: invoice paid, payment failed, subscription updated, trial will end. - Scheduled jobs: weekly or monthly digests, quota alerts, stale project nudges. Send from a queue rather than inline in HTTP requests. Persist an `EmailLog` with fields such as `userId`, `template`, `locale`, `status`, `error`, and an `idempotencyKey`. This gives you retries, backoff, and support visibility. Add a guard that prevents repeat sends of one-time links within a short window. For links, sign tokens server-side and set explicit expiries. Prefer scoped, single-use tokens for sensitive actions and short, revocable sessions for magic links. Always include a manual URL fallback in case buttons are stripped. ## Testing checklist and edge cases - Inbox coverage: Gmail, Outlook, Apple Mail, iOS, and Android clients. - Dark mode: ensure contrast and button colors remain readable. - Plain text: contains the same core info and URLs as HTML. - Localization: long strings, umlauts and accents, RTL layout, plural rules. - Formatting: very large numbers, different currencies, and time zones crossing DST. - States: free trials, annual plans, coupons, taxes and VAT IDs, failed renewals, empty usage. - Security: expired token flow, reused token, and invalid token messaging. - Deliverability: throttle digests, verify from domain, monitor bounces and spam complaints. ## What a good starter gives you so you can ship fast The right Nuxt starter kit removes glue work. Pre-built transactional templates save hours because structure and styles are already tested. Auth and payments modules emit clean events. An in-app language switch keeps localization consistent across UI and email. Scheduled cron jobs handle summaries and reminders. Admin tools let support resend key emails safely. Deployment presets include provider credentials and environment variables so production matches staging. That is the difference between moving tickets and moving revenue. If you need a Nuxt SaaS starter kit or Nuxt SaaS template to stand up quickly, make sure these pieces are included and documented. They matter more in week two, when your focus shifts from launch to retention. Transactional emails do quiet but essential work. Put these seven Nuxt email templates in place early and you will reduce confusion, lower support load, and raise activation and recovery without changing your product roadmap. Whether you code from scratch or use a Nuxt boilerplate, treat email as a first-class surface. Your users will feel the difference, and your metrics will reflect it. ### Key takeaways - Ship seven core templates first: welcome, verify, security alerts, receipts and dunning, usage digests, re-engagement, and trial or renewal reminders. - Localize server-side, design for plain-text and dark mode, and protect deliverability with proper auth and throttling. - Wire templates to auth events, payment webhooks, and scheduled jobs in a queue so sends are reliable and observable. - Pick a starter that includes templates, a language toggle, admin resend tools, and cron so you can focus on product and ship fast. ## FAQ ### What are the essential Nuxt email templates for a new SaaS? Start with welcome, verification or magic link, password reset and security alerts, receipts and subscription updates, usage summaries, re-engagement, and localized test emails. ### How often should I send usage summaries? Weekly works for most products. Offer monthly for low-activity users and let users change the frequency or opt out to protect deliverability. ### How do I localize transactional emails in Nuxt? Keep copy in translation files, localize currency and dates server-side, and preview each language. Use an in-app language switch so emails and UI stay in sync. ### What triggers should send billing emails? Successful payments, failed charges, trial ending, plan changes, refunds, and renewals. Include details and a manage-subscription link in each message. ### How can I test my email templates before launch? Render templates with seeded data, send to real inboxes across providers, check dark mode and plain-text versions, and test every link and expiry. # Nuxt Folder Structure: A Practical Step-by-Step Guide ![A practical Nuxt folder structure guide with setup steps, examples, and pitfalls to avoid so your SaaS stays organized, predictable, and ready to ship.](https://shipahe.ad/images/blog/nuxt-folder-structure-step-by-step-guide/post-745.webp){style="max-width:100%;border-radius:12px"} Nuxt lets you move fast. Speed fades when folders drift, names get vague, and every new screen needs a scavenger hunt. A crisp Nuxt folder structure keeps work predictable, reviews short, and changes safe. The patterns below hold up for MVPs and full SaaS apps with auth, billing, admin, i18n, and AI features. The aim is simple. Make it obvious where things live, keep layers thin, and let Nuxt conventions do the wiring so you write feature code, not glue. ## How Nuxt maps folders to behavior Nuxt favors convention over custom setup. Use these defaults and your app stays discoverable as it grows. - **pages/**. Files become routes. *pages/index.vue* is */*. *pages/pricing.vue* is */pricing*. Dynamic and nested routes use brackets and folders like *pages/users/\[id].vue* and *pages/users/\[id]/settings.vue*. Catch all with *\[...slug].vue* when needed. - **layouts/**. Page wrappers. Add *layouts/default.vue* and any section-specific layout such as *layouts/dashboard.vue*. Opt in from a page with *definePageMeta({ layout: 'dashboard' })*. - **components/**. Auto imported by name. Favor domain folders like *components/billing/CardForm.vue* and *components/admin/UserTable.vue*. Use clear nouns so intent is obvious wherever the component is used. - **composables/**. Auto imported functions that hold state or logic. Use the *useX* naming pattern, for example *composables/auth/useSession.ts* or *composables/billing/useInvoices.ts*. Keep them pure and testable. - **middleware/**. Route middleware files, run before a page renders. Create *middleware/auth.ts* and call it by name in pages via *definePageMeta({ middleware: 'auth' })*. Add *\*.global.ts* to run on all routes when you truly need it. - **plugins/**. Initialization that runs before app mount. Provide injections like *$analytics* or *$payments*. Scope to client or server with *.client.ts* or *.server.ts*, for example *plugins/analytics.client.ts*. - **server/api/**. Nitro server routes. File names map to endpoints and HTTP methods, such as *server/api/invoices.get.ts*, *server/api/invoices.post.ts*, or *server/api/billing/webhook.post.ts*. Keep business logic in server utils, not inlined in handlers. - **assets/** vs **public/**. *assets/* is built by Vite and supports imports in Vue and CSS. *public/* is served as-is at the site root. Put imported images, fonts, and styles in *assets/*. Put files referenced by URL, like */robots.txt* or */images/og-cover.jpg*, in *public/*. - **app.vue** and **app.config.ts**. Your app shell and app-level meta. Centralize default SEO, headers, theme color, and root layout concerns here. - **error.vue**. Global error UI for unhandled exceptions and 404s. Keep it minimal and fast. ## A clean, repeatable structure in 7 steps ### 1) Create the baseline directories Start with *pages/*, *layouts/*, *components/*, *composables/*, *plugins/*, *middleware/*, *server/api/*, *assets/*, *public/*, *app.vue*, and *app.config.ts*. That backbone prevents ad hoc folders later. ### 2) Group by feature inside the standard folders Favor domain folders rather than deep nested pages. Keep Nuxt auto imports working by nesting inside conventional folders. - Pages: *pages/billing/index.vue*, *pages/billing/subscribe.vue*, *pages/account/index.vue* - Components: *components/billing/CardForm.vue*, *components/account/ProfileForm.vue* - Composables: *composables/billing/useInvoices.ts*, *composables/account/useProfile.ts* - API: *server/api/billing/checkout.post.ts*, *server/api/account/profile.get.ts* Rule of thumb: if a feature spans pages, UI, logic, and API, it earns a folder with the same name across those layers. Anyone can jump to the feature across the stack in seconds. ### 3) Use clear naming conventions - Components in **PascalCase** with a concrete noun, optionally prefixed by domain: *BillingPlanPicker.vue*, *InvoiceTable.vue*, *CardForm.vue*. - Composables prefixed with **use** and a verb or domain: *useInvoices.ts*, *billing/useCheckout.ts*, *auth/useSession.ts*. - API routes with method suffixes: *invoices.get.ts*, *checkout.post.ts*, *users/\[id].patch.ts*. - Route files in **kebab-case**: *user-settings.vue*, *team-members.vue*. Keep route depth shallow and link deeper UI via components. ### 4) Keep auth and access control obvious Put route guards in *middleware/auth.ts* and call them from protected pages using *definePageMeta({ middleware: 'auth' })*. For server routes, check the session at the top of each handler and bail fast on failure. Create *pages/auth/* for login, register, and reset. Put all protected app screens under a clear path like *pages/app/* or use a dedicated *dashboard* layout so access control stays visible in code review. ### 5) Isolate integrations in plugins Initialize third-party clients in *plugins/* and expose a single injection. Examples include analytics, a payment SDK, feature flags, and an i18n client. Use *.client.ts* for browser-only libraries and *.server.ts* for server-only setup. Keep business rules out of plugins and inside composables or server utils. ### 6) Separate static files from processed assets Images imported in components belong in *assets/* so Vite can optimize them. Files referenced by absolute path live in *public/*. This avoids surprising bundle size changes and broken URLs during deploys. ### 7) Keep environment and runtime config tidy Put secrets in *.env* and map them into Nuxt runtime config. Expose only what the browser needs in *runtimeConfig.public*. Co-locate any shared types for config in *types/*. Do not import *process.env* across your app; read from runtime config in server and composables. ## SaaS-ready examples by feature Map common SaaS features to Nuxt folders so everything lines up the same way in every project. - **Authentication** - Pages: *pages/auth/login.vue*, *pages/auth/register.vue*, *pages/auth/reset.vue* - Composables: *composables/auth/useSession.ts*, *composables/auth/useMagicLink.ts* - API: *server/api/auth/login.post.ts*, *server/api/auth/callback.get.ts* - Middleware: *middleware/auth.ts* for protected pages - **Billing** - Pages: *pages/billing/index.vue*, *pages/billing/subscribe.vue* - Components: *components/billing/PlanPicker.vue*, *components/billing/CardForm.vue* - Composables: *composables/billing/usePlans.ts*, *composables/billing/useCheckout.ts* - API: *server/api/billing/checkout.post.ts*, *server/api/billing/webhook.post.ts* - **Internationalization** - Plugins: *plugins/i18n.client.ts* to register the i18n instance - Locales: *locales/en.json*, *locales/fr.json* with keys grouped by feature - Components: *components/i18n/LanguageSwitcher.vue* for in-app language changes - **Admin** - Pages: *pages/admin/index.vue*, *pages/admin/users.vue* - Layout: *layouts/dashboard.vue* for nav, sidebar, and breadcrumbs - API: *server/api/admin/users.get.ts*, *server/api/admin/ban.post.ts* - **AI features** - Pages: *pages/ai/chat.vue*, *pages/ai/generate.vue* - Composables: *composables/ai/useChat.ts*, *composables/ai/useImageGen.ts* - API: *server/api/ai/chat.post.ts*, *server/api/ai/image.post.ts* If you are asking “How do I build and sell an AI tool online”, this mapping keeps auth, billing, and AI endpoints obvious from day one so you spend time on product behavior, not wiring. ## Scaling without chaos ### Practical guardrails - **Prefer feature folders over deep nesting.** Keep routes shallow. Push complexity into components and composables so URLs stay readable and reviews focus on one concern at a time. - **Use layouts for app sections.** A *dashboard* layout can own nav and chrome. Pages stay about content and data fetching. - **Write a naming guide and enforce it.** Add it to *CONTRIBUTING.md*. Lint and types in CI prevent broken imports and implicit any types from slipping in. - **Document server endpoints.** Keep a short *server/README.md* with routes, owners, and payload shapes. It pays for itself the first time you are on-call. ### Common pitfalls to avoid - **Mixing assets and public.** Imported assets go in *assets/*. Files served by URL only go in *public/*. Mixing them causes bad caches and broken links. - **Hiding logic in plugins.** Plugins initialize libraries and provide injections. Put business logic in composables and server utils so it can be tested and reused. - **Ambiguous component names.** *Table.vue* is noise. *InvoiceTable.vue* or *UserTable.vue* explains intent instantly. - **Dynamic routes without validation.** Always validate params in server handlers. Use explicit types in composables that consume them. - **No boundary between public and protected pages.** Use a clear path like *pages/app/* or a dedicated layout. Apply *auth* middleware every time. When work goes beyond housekeeping, a partner like RedStudio can audit routes, components, and server handlers and suggest a pragmatic path to consolidate or split features. ## When a starter kit saves weeks If you would rather buy a Nuxt boilerplate and skip weeks of setup, a Nuxt SaaS starter kit provides a proven layout and production features. For example, the Nuxt SaaS boilerplate offered on shipahe.ad includes user authentication with email, password, magic links, and Google, protected pages, an admin panel, checkout flows for one-time or subscription payments with multiple providers, multi-language support with an in-app switch, transactional emails, a preconfigured database with an ORM, S3 compatible file storage, AI chat and generation tools, scheduled cron jobs, a blog, built-in analytics, and SEO tools. That frees your structure to focus on features instead of wiring signups, billing, and admin. If you already have a codebase, you can still adopt a Nuxt starter template pattern over time. Move view files into *pages/*, extract logic into *composables/*, and fold server work into *server/api/*. Whether you call it a Nuxt starter kit, a Nuxt SaaS template, or a SaaS starter kit, the goal is the same. Make the tree predictable so you can add screens without rereading the whole app. ### Key takeaways - Let Nuxt conventions guide your folders so discovery and auto imports work for you. - Group by feature inside standard directories. Keep routes shallow, move logic into composables. - Name files for what they do. Prefer explicit names over generic ones. - Use plugins for setup, middleware for access control, and *server/api* for backend work. - Reach for a Nuxt SaaS boilerplate when you want production features and a sane structure on day one. ## FAQ ### What belongs in assets versus public in a Nuxt app? Put styles and images you import from components in assets. Put files you want at stable URLs, like favicons, robots.txt, or large downloads, in public. ### Where do I put API routes in Nuxt 3? Place them in server/api. Name files with HTTP method suffixes like users.get.ts or checkout.post.ts. Nuxt’s Nitro server will route requests automatically. ### Should I use a src directory with Nuxt? You can. Many teams keep the root simple and place app files at the project root. If you prefer src/, configure it and keep tests, scripts, and tooling outside it. ### How can I organize large features without losing auto imports? Nest by domain inside components, composables, pages, and server/api. Nuxt will still auto import components and composables from subfolders. ### How do I migrate an existing Vue app into Nuxt without chaos? Move routes into pages first to get routing under control, extract shared logic into composables, and then migrate API calls into server/api handlers. # Nuxt Middleware: A Practical Guide for SaaS and AI Apps ![Use Nuxt 3 middleware to guard auth, subscriptions, locales, admin, and analytics. Concrete patterns, code, and pitfalls for SaaS and AI apps.](https://shipahe.ad/images/blog/nuxt-middleware-practical-guide-saas-ai-apps/post-692.webp){style="max-width:100%;border-radius:12px"} If your app has logins, paid features, multiple languages, and an admin area, routing rules pile up fast. Nuxt middleware keeps those rules consistent, testable, and easy to change without scattering checks across components. Below is a practical stack we use on SaaS and AI tools. It favors small, named middlewares, clear redirects, and server-first checks so users never see protected pages flash. ## What middleware does in Nuxt 3 Nuxt 3 gives you two layers: - **Route middleware**. Runs before navigating to a page. Ideal for auth, plan gating, locale redirects, analytics. Files live in */middleware*. Name them for selective use, or add *.global* to run on every navigation. - **Server middleware**. Runs on the server for every request handled by Nitro. Use it for request logging, bot filtering, strict headers, and webhook signature checks. Files live in */server/middleware*. Route middleware runs on both server and client. You can make decisions on the first request on the server to avoid flicker, then reuse the same checks on the client for internal navigations. ``` ``` ## Build a reliable middleware stack 1. ### Write the rules before code List the routes and the guardrails they need. A typical SaaS set: - Public routes anyone can view. - Protected routes for logged-in users. - Paid routes for active subscribers. - Admin-only routes for your team. - Language-aware routes that honor a user’s locale. :brWrite the behavior and the failure path in plain language. Example: “If a non-subscriber visits /generate, redirect to /pricing and remember where they came from.” This becomes the acceptance test for your middleware. 2. ### Create an authentication guard Add */middleware/auth.ts* and redirect to login when there is no session. Always carry the intended destination. ``` ``` :brIf you use a Nuxt SaaS starter, session state and redirects are already wired, so the guard is a thin wrapper around a single source of truth. 3. ### Gate paid features Check subscription status in */middleware/paid.ts*. If missing or expired, send users to pricing or checkout and preserve the next URL. ``` ``` :brKeep plan state cached in session or a small store that is filled on login or page load so the middleware does not trigger extra round trips. 4. ### Protect admin routes Verify role in */middleware/admin.ts*. Fail closed to a safe page. ``` ``` :brMirror the role model from your Admin Panel to avoid drift. Admin checks should be strict and boring. 5. ### Handle language with a global locale middleware Pick a default on first visit, then respect user choice. Prefix the filename to control order. ``` ``` :brLet the in-app language switch update the cookie or profile so the middleware follows the user’s decision. 6. ### Track analytics without flicker Record pageviews in a global middleware. Emit on the server when possible, then fall back to a client call. ``` ``` :brKeep event names consistent so you can answer, “Which protected routes cause the most logins?” or “Which plan gates are hit most often?” 7. ### Use server middleware for low-level checks Put request-wide concerns in */server/middleware*. Keep handlers fast and stateless. ``` ``` 8. ### Attach middleware in one obvious place Use named middleware in pages via `definePageMeta`. Leave a short comment at the top describing the policy. ``` ``` :brDocument exceptions in the same way. Login, signup, pricing, and error pages should be exempt from *auth* and *paid*. ## Patterns that hold up in production ### Guest-to-paid upgrade A public landing page links to an AI feature page that requires both *auth* and *paid*. If the visitor is logged out, send them to sign up. If logged in but not paid, send them to checkout. On success, return to the feature page with inputs intact so they can continue the workflow. ### Localized onboarding The first visit sets the initial locale from headers and redirects to a language-prefixed path. Thereafter, respect the user’s switch. This avoids loops and fights with the user’s choice. ### Admin-only moderation Admin routes run the *auth* and *admin* middlewares. Fail closed to the dashboard. Keep the Admin Panel and middleware checking the same role source of truth. ### AI usage gates Gate costly operations like generation, uploads, or long-running jobs. Apply *auth* and *paid* to chat, text, and image routes. That lets you measure demand and control spend from day one. ## Pitfalls, tests, and tooling - **Infinite redirects**. Whitelist login, signup, pricing, and error pages. Add a quick check at the top of *auth* and *paid* to skip on those routes. - **Client-only checks cause flicker**. Ensure the critical checks run during the first server navigation so protected content never flashes. - **Slow async in middleware**. Do not fetch user or plan data on every navigation. Hydrate a small store on login or initial load and read from it. - **Order surprises**. Global middlewares run in filename order. Prefix them, for example *10-locale.global.ts* and *20-analytics.global.ts*, so intent is obvious in reviews. - **Untested failure paths**. Write unit tests for each rule and a few end-to-end checks: expired plan, revoked admin role, missing locale cookie. Middleware is small, but everything around it is not. A ready-to-buy Nuxt boilerplate removes a lot of setup. The shipahe.ad Nuxt starter includes protected pages, multiple authentication options, payment processing for one-time and subscriptions, multi-language support, transactional emails, a typed database with ORM, S3-compatible file storage, AI chat and generation with switchable models, cron jobs, a blog powered by Nuxt Content, analytics tracking, SEO tools, and a prebuilt landing page. It is built to work well with AI coding tools like Cursor and Claude. As you refine rules, capture what feels rough for users. A public feedback workflow makes patterns obvious. See their [practical guide to product feedback and running a feature voting board](https://www.feedjolt.com/en/blog/product-feedback-management-for-startups-practical-guide){rel=""dofollow""} for a simple way to collect requests, auto-merge duplicates, and rank what to build next. If you want a Nuxt SaaS starter that keeps middleware focused on policy while auth, payments, i18n, and analytics are already wired, a production-grade template will save weeks. Buy a boilerplate when you want to launch sooner and spend your time on product value, not plumbing. ## Key takeaways - Write routing rules in plain language first, then encode them as small, named middleware. - Use global middleware for locale and analytics, named middleware for auth, paid, and admin. - Run checks on the server during the first load to avoid flicker and leaks. - Keep middleware fast. Cache what you can and test failure paths. - A solid Nuxt starter kit gives you the surrounding auth, payments, i18n, and tracking so middleware stays simple. ## FAQ ### What is the difference between route middleware and server middleware in Nuxt 3? Route middleware runs before navigating to a page and is great for auth, plan checks, locale, and analytics. Server middleware runs on every server request and is better for low-level tasks like request logging or webhook signature checks. ### Where should I put Nuxt middleware files? Put route middleware in the /middleware directory. Add .global to the filename for middleware that should run on every navigation. Put server middleware in /server/middleware. ### How do I prevent infinite redirects with auth middleware? Exclude login, signup, pricing, and error pages from auth and paid checks. Also remember to pass the original destination as a query so you can return the user after login or checkout. ### Can I run async code inside middleware? Yes, but keep it minimal and cache results. For example, store plan status on login so your paid middleware does not fetch it repeatedly on every navigation. ### How do I test Nuxt middleware? Write unit tests for each middleware function and add a few end-to-end tests for critical routes. Test both success and failure paths, including expired plans and missing roles. ## Recommended resources - [practical guide to product feedback and running a feature voting board](https://feedjolt.com) # Nuxt Modules That Ship: Install, Configure, and Launch ![Practical Nuxt modules guide: pick a lean stack, wire it in nuxt.config, add auth, payments, i18n, admin, and avoid gotchas that slow SaaS launches.](https://shipahe.ad/images/blog/nuxt-modules-install-configure-build-faster/post-742.webp){style="max-width:100%;border-radius:12px"} Nuxt ships with a lot of batteries, but module sprawl can stall a launch. After building and selling real products, my rule is simple: pick a small, predictable set of Nuxt modules, wire them with intention, and write just enough glue code to deliver revenue features. This walkthrough shows the exact setup and patterns we use to get a SaaS, an AI tool, or an internal web app live without surprises. ## Nuxt modules in practice: what they change Nuxt modules are installable packs that hook into build and runtime. They can add components and composables, adjust Vite, inject server routes, register plugins, and expose typed options. The win is focus: each module removes a slice of plumbing you would otherwise rewrite. - Build time: tweak Vite, transform code, auto-import components and composables, generate types, or alias paths. - Runtime: register plugins, server routes, middleware, and runtime config your app consumes while running. Concrete use cases that consistently pay off: - Styling and UI: Tailwind CSS for design system tokens and utility classes; Nuxt Image for optimized images with smart formats. - State and utilities: Pinia for predictable stores; VueUse for browser and reactivity helpers you would otherwise hand-roll. - Internationalization: @nuxtjs/i18n for locale routing, lazy-loaded messages, and language detection. - Auth and security: an auth module or custom middleware with typed session handling and server-only secrets. - DX: Devtools, auto imports, and type helpers that reduce footguns in large projects. If the question is how to build and sell an AI tool online, the answer is rarely “add more modules.” It is “pick three to five modules that remove obvious toil, then ship a thin slice end to end.” ## Set up a lean stack: install and configure ### 1) Create a fresh Nuxt app ``` ``` ### 2) Install only what you will use this week A dependable starter set: - UI and images: @nuxtjs/tailwindcss, @nuxt/image-edge - State and utilities: @pinia/nuxt, @vueuse/nuxt - i18n: @nuxtjs/i18n (only if you plan multiple languages now) ``` ``` ### 3) Register modules in nuxt.config with tight options Keep options close to the module. Make defaults explicit so upgrades do not surprise you. ``` ``` ### 4) Put secrets in runtimeConfig and fail fast Never hardcode provider keys. Use runtimeConfig and your deployment platform’s env vars. Add a startup assertion so a missing key fails locally before it fails in prod. ``` ``` ``` ``` ## Turn modules into SaaS features Map each feature to one or two modules plus a little glue. Resist stacking overlapping packages. ### Authentication and protected pages - Use route middleware for access rules. Annotate public routes with `meta.public = true`. - Keep the user in a single source of truth, such as a Pinia store fed by a server endpoint. ``` ``` ### Payments and subscriptions - Store provider keys in runtimeConfig. Never expose them to the client. - Handle webhooks on the server to update subscriptions, invoices, and entitlements. ``` ``` ### Internationalization in the UI - Drive copy from JSON, grouped by feature to avoid duplication. - Add a simple locale switcher. Keep flags out of it; use language codes. ``` ``` ### Admin area - Protect routes with role checks in middleware and on the server. - Use server-side filtering and pagination for large tables to keep TTFB low. ### Case study: captions feature in a week Suppose you are building a small AI tool that burns captions onto short videos. Keep the stack minimal: file uploads, a queue or cron job for processing, a page to preview and download the result, and i18n so captions can be localized. For expectations and UI flow, study a clear, production-ready workflow like this article on [how to add subtitles to video online](https://subtitlesfast.com/blog/instagram-reels-captions-add-style-and-export-cleanly){rel=""dofollow""}. Mirror the clarity in your editor and export steps while you build your own pipeline behind the scenes. If you prefer to skip scaffolding and start from a proven base, our Nuxt SaaS boilerplate (shipahe.ad) includes protected pages, multiple authentication providers, an admin area, billing with checkout flows, a locale switcher, transactional email, a preconfigured database and ORM, S3-compatible file storage, analytics, SEO helpers, AI chat and generation with switchable models, scheduled cron jobs, and a landing page. You focus on your domain logic; the wiring is done. ## When a tiny custom module beats copy-paste When behavior repeats across apps, a small custom module keeps code local and configurable. This example adds a server endpoint and exposes a public runtime setting. ``` ``` ``` ``` ``` ``` This pattern shows how to add a server route from a module, pass options with sane defaults, and surface a typed public config without scattering it through the app. ## Operate, monitor, and prune - Run `pnpm dev` with the console visible. Fix SSR and deprecation warnings immediately; they compound during upgrades. - Track usage. If your starter includes analytics, review which routes get traffic before you add features or libraries. - Profile bundle size. Use a Vite visualizer and remove modules with heavy client payloads that do not move key metrics. - Audit environment variables in staging first. Many runtime features silently degrade with missing keys. - Pin versions. Upgrade Nuxt, Vite, TypeScript, and modules in small steps, reading changelogs as you go. ### Common pitfalls - Module order surprises: modules that patch Vite or auto imports may need to load earlier. - Server vs client confusion: do not call browser APIs in server plugins; use `process.client` checks or client-only plugins. - Duplicate functionality: pick one image solution, one state library, one i18n solution. - Environment drift: add startup checks to fail fast when keys are missing in production. ::div{.key-takeaways} ### Key takeaways - Pick a short list of Nuxt modules tied to outcomes, not a wishlist. - Keep configuration close to each module and put secrets in `runtimeConfig`. - Use route middleware and server endpoints to enforce auth and billing rules. - Write tiny custom modules for repeatable glue code across projects. - Measure usage and bundle size, then prune. Shipping small wins. :: Whether you assemble your own Vue Nuxt starter template or start from a Nuxt boilerplate to move fast, modules are the difference between hobby code and a maintainable product. Used well, they turn an idea into a working SaaS in days, not months. ## FAQ ### What are nuxt modules in simple terms? They are installable packages that extend Nuxt at build time and runtime. Modules can add plugins, routes, config, and tooling so you write less boilerplate. ### How many nuxt modules should I start with? Start with 3 to 6 essentials tied to outcomes like styling, state, images, and i18n. Add more only when a real need appears in your roadmap. ### Do nuxt modules work in serverless deployments? Yes, as long as the module’s server features are compatible with Nitro. Keep secrets in runtimeConfig and rely on server routes for secure tasks. ### Should I write a custom module or a plugin? If you only need client or server runtime code in one app, a plugin is fine. If you need build-time hooks, config, or to reuse code across apps, write a module. ### How do I protect pages with auth using Nuxt? Create route middleware that checks for a user state and redirects unauthenticated users to login. Keep credentials and tokens off the client. ## Recommended resources - [how to add subtitles to video online](https://subtitlesfast.com) # Nuxt multi-tenant SaaS architecture patterns that scale ![A practical guide to nuxt multi-tenant SaaS design. Learn viable routing, shared-DB isolation, billing, and testing patterns that scale without surprises.](https://shipahe.ad/images/blog/nuxt-multi-tenant-saas-architecture-patterns-that-scale/post-342.webp){style="max-width:100%;border-radius:12px"} Building a multi-tenant SaaS on Nuxt 3 and Nitro is a sequence of high-leverage decisions. Get tenant identity right, scope every request, enforce isolation in the database, and wire billing to entitlements. Do this early and you can ship in weeks, then scale tenants, traffic, and teams without rewrites. This guide gives concrete patterns you can implement in a new Nuxt app or layer onto an existing codebase. Each choice is framed so it is easy to ship now and safe to evolve later. ## Tenancy foundations that scale in Nuxt Multi-tenant means many customers share one application stack. You trade some isolation for speed and cost efficiency. Start simple, but design the seams so you can increase isolation as needs grow. ### Single-tenant vs multi-tenant at a glance - **Single-tenant:** One customer per stack. Maximum isolation, high cost. Choose it only when contracts or data residency make it mandatory. - **Multi-tenant:** Many customers on one stack. Lower cost, more complexity. The default for most early-stage Nuxt apps. ### Tenant identity drives everything - Create a first-class `tenants` table with `id` (UUID), `slug`, `plan`, `status`, `trial_ends_at`, and timestamps. - Model membership with a join table like `tenant_users` holding `tenant_id`, `user_id`, and `role` (owner, admin, member, viewer). - Every tenant-owned record carries `tenant_id`. Keep truly global tables separate. - Expose tenant context in both the client (a composable) and the server (request-scoped object) so every layer can enforce it. ### Isolation levels you can evolve through - **Row-level in a shared database:** Single Postgres instance, tables carry `tenant_id`. Use composite unique indexes like `(tenant_id, slug)`. Consider Row Level Security policies to enforce scoping in the database. This is the fastest path to production. - **Schema-per-tenant:** Still one database server, each tenant has its own schema. Stronger blast radius control but more migrations and connection juggling. - **Database-per-tenant:** Highest isolation short of single-tenant. Operationally heavy. Adopt for regulated customers or very large tenants. ## Routing and request scoping Your routing model sets cookie scope, perceived brand quality, and how easy observability will be. Choose once, then apply it consistently across SSR, server routes, and static assets. ### Subdomain per tenant Pattern: `acme.example.com`. Parse the host in a Nitro server middleware, resolve the tenant by `slug`, and attach it to the event context. Benefits: clean session separation, analytics by host, and straightforward custom-domain support later. For custom domains, verify DNS ownership on onboarding, store the mapping, and let your edge terminate TLS per host. Keep cookie domains scoped to the subdomain so tenants cannot see each other’s sessions. ### Path-based tenancy Pattern: `/t/acme/...`. Resolve the slug from the path and fetch the tenant in a route middleware. It is easy to host anywhere and avoids wildcard DNS. Be strict about internal links always including the tenant segment to prevent cross-tenant navigation. Favor absolute paths that include the resolved slug. ### Tenant-aware middleware in Nuxt - Create a small server middleware that resolves `tenant` from host or path and fails closed if not found. - Expose a `useTenant()` composable that reads the server-provided context on SSR and hydrates a client store. Do not let components guess. - Order of operations: resolve tenant, then locale. Keep the i18n switch tenant-aware so language changes never drop the tenant prefix. - Protect caching: add a Surrogate-Key or Vary header that includes `tenant_id` so edge caches and CDNs cannot bleed content across tenants. ## Data isolation and storage Start with a shared Postgres database and row-level scoping. Treat `tenant_id` as non-negotiable and enforce it at the ORM and database levels. ### Modeling and constraints - Add `tenant_id` to every multi-tenant table. Use composite unique keys for namespaced uniqueness, for example `(tenant_id, email)` or `(tenant_id, slug)`. - Prefer foreign keys that include `tenant_id` to stop cross-tenant references. A common pattern is a composite FK on `(id, tenant_id)` pairs. - Use a typed ORM and repositories that always require `tenant_id`. Ban queries that accept only a primary key. Add helpers that auto-stamp `tenant_id` on inserts. - Design for soft deletes with `deleted_at`. Add partial indexes to keep lookups fast while ignoring deleted rows. ### Files and storage - Use S3-compatible storage with a prefix like `tenants/{tenant_id}/...`. Never store tenant-owned files at the root. - Keep file metadata in the database with `tenant_id`, size, checksum, and content type. Validate metadata before issuing a download. - Serve uploads with short-lived presigned URLs and enforce content disposition to avoid leaking file names. - Apply lifecycle policies per prefix to expire archives and comply with retention rules. ### Scheduled jobs and background work - Drive cron tasks by iterating tenants in small batches and passing `tenant_id` into each job payload. Keep jobs idempotent with an idempotency key per tenant and day. - Bound retries and isolate noisy tenants by limiting concurrency per tenant. A single failing job must not block the global queue. - For long-running work like exports or AI generation, store progress rows keyed by `tenant_id` so the UI can poll safely. ## Billing and lifecycle controls Without billing, tenancy is a hobby. Bind access to a subscription or one-time purchase and express plan rules as enforceable checks at the server boundary. ### Checkout, entitlements, and limits - Bind subscriptions to `tenant_id`, not users. A user can belong to multiple tenants with different roles and plans. - Express plan rules in code and data. A simple `entitlements` table with keys like `max_users`, `max_projects`, `ai_tokens_per_month`, and `file_storage_mb` makes checks simple and auditable. - On successful checkout, upsert the subscription, store the current period, and emit a domain event so the app can enable features and send emails. ### Trials, seats, and usage-based features - Track seat counts on the tenant. Enforce limits in the invite flow and surface an upgrade CTA if the cap is reached. - Handle past-due gracefully. Keep access to data, restrict premium features, and schedule retries. End with a clear downgrade state if payment fails. - For AI tools and content generation, meter usage per tenant. Count tokens, requests, or images, store them with `tenant_id` and billing period, and cap or throttle when the entitlement is exhausted. ### Admin controls - Provide a staff-only Admin Panel to view tenants, users, subscriptions, and recent events. - Require elevated roles for dangerous actions like bans and refunds. Log who did what and when for every mutation. - Allow safe user impersonation for support with a visible banner and automatic revert, recording an audit entry. ## Testing and observability by tenant Multi-tenant bugs hide in edges and defaults. Make tests and telemetry tenant-aware from day one. ### Automated tests that assert isolation - Seed at least two tenants in fixtures and run every read and write twice: Tenant A cannot see Tenant B. - Write end-to-end flows for signup, invite, checkout, upgrade, and downgrade. Tools like FlyTrap help explore flows and generate tests that surface cross-tenant navigation errors. - Add smoke tests that verify middleware blocks requests without a resolved tenant. ### Feature flags and migrations - Roll out risky features to a subset of tenants. Keep the flag check on the server so it cannot be bypassed by the client. - Rehearse migrations on a staging snapshot. Include backfills that are idempotent and safe to retry under load. - Instrument each migration with timing and row counts per tenant so you can spot outliers before they hit production. ### Logs, metrics, and analytics - Attach `tenant_id` to every log line, trace, and metric. Include the user id and request id for correlation. - Track per-tenant pageviews, signups, invites, and billable events. Use these to plan capacity and discover churn risks. - Alert on error rates and latency by tenant so a noisy customer cannot hide global issues, and a global incident is obvious. Want to ship faster without rebuilding basics? A Nuxt SaaS starter kit gives you authentication, protected pages, a typed database with an ORM, i18n with an in-app language switch, an Admin Panel, scheduled jobs, and ready-to-wire one-time or subscription payments keyed to `tenant_id`. Shipahe.ad packages these into a Nuxt boilerplate with deployment tooling so you can focus on plan limits, data modeling, and the features that make your product valuable. ## Key takeaways - Decide tenant identity first and expose it in middleware, composables, and the database. Everything hangs on `tenant_id`. - Start with a shared Postgres database and row-level scoping. Evolve to schema or database per tenant only when contracts or scale demand it. - Pick one routing model and enforce tenant context everywhere. Cache and cookies must be tenant-aware. - Tie subscriptions to tenants and enforce entitlements in server routes. Be generous with data access during billing issues. - Test isolation continuously and stamp `tenant_id` on logs, traces, and metrics. Observability makes support and scaling sane. # Nuxt Plugin Playbook: Ship Faster with 15 Real Patterns ![A practical Nuxt plugin playbook for SaaS: auth, payments, i18n, SEO, analytics, AI, marketplace hooks, plus when a Nuxt starter kit is the faster path.](https://shipahe.ad/images/blog/nuxt-plugin-playbook-15-practical-uses-to-ship-faster/post-743.webp){style="max-width:100%;border-radius:12px"} Shipping a SaaS means turning shared behavior into small, predictable building blocks. A good Nuxt plugin gives you a single place to wire capabilities, test them, and expose a clean API to the rest of the app. Here is a practical playbook for what belongs in plugins, with concrete patterns you can ship this week, plus when a Nuxt SaaS starter kit is the faster move. ## Authentication, email, and admin control **Centralize authentication.** Wrap sign up, login, logout, token refresh, and session hydration in one plugin so pages and components call a stable API. Expose helpers like `$auth.login`, `$auth.user`, `$auth.require`, and `$auth.hasRole`. Keep tokens in httpOnly cookies, not localStorage. Use route middleware to protect pages and server route rules to block access at the edge. Support email and password, magic links, and Google with identical UI flows, and keep provider differences hidden inside the plugin. **Guard admin early.** Put admin authorization in a single injection: `$admin.isAllowed()` and `$admin.fetch` for privileged API calls. Register route middleware that denies non-admins before the page renders. Prefer server-rendered admin tables with pagination to avoid leaking data into the client. Keep an explicit allowlist of admin-only components so you do not accidentally mount them for regular users. **Send transactional email from a thin client.** The UI should never talk to an email provider directly. Expose `$mail.sendWelcome`, `$mail.sendReset`, and `$mail.sendNotification` in a plugin, then route those calls to server handlers that fill templates, set idempotency keys, and call your provider (Postmark, SES, Mailgun). Keep templates versioned with the app and add a preview route in development so writers can review copy without shipping code. ## Billing, files, and data plumbing **Abstract payments behind one client.** Provide `$payments.checkout` for one-time purchases and subscriptions, `$payments.portal` for self-serve changes, and `$payments.status` for entitlement checks. Hide provider specifics (Stripe, Paddle, Lemon Squeezy) behind the plugin. Run webhooks on the server to mark invoices paid, advance trials, and cancel on failure. Keep plan logic in one place so feature flags read `$auth.plan.allows('ai.image')` instead of scattering `if (plan === 'pro')` checks. **Inject your ORM in a server plugin.** Initialize Prisma or Drizzle in a server-only plugin and inject typed repositories like `db.user` and `db.subscription`. Use a connection pool that works on your host (for example, PgBouncer on Postgres) and reuse clients across requests to avoid cold starts. Ship migrations from the same repo and run them in CI so schema and code land together. **Handle uploads with signed URLs.** Expose `$files.getSignedUrl` and `$files.upload` that return secure, time-limited S3-compatible URLs. Keep buckets private and gate reads with short-lived signatures. Store only the object key in your DB. For the UI, accept a `File`, call `$files.upload('avatars/user-123.png', file)`, then save the returned key. Add image resizing on write (Lambda, Cloudflare Images) so you do not serve 10 MB photos to mobile users. **Schedule recurring work safely.** Register a small set of cron tasks in a server plugin. Each task should be idempotent, log its work, and accept a time window so retries are safe. Trigger them with your host’s scheduler hitting a signed internal endpoint like `/internal/cron?token=...`. Typical jobs: daily usage digests, payment dunning emails, deleting expired uploads, and generating weekly product analytics. ## UX, content, and growth **i18n with a toggle that sticks.** Initialize your translation library in a plugin, load locale messages lazily, and remember the user’s choice in a cookie so SSR renders in the right language. Provide `$i18n.setLanguage(lang)` and `$i18n.t(key)`. Use route middleware to redirect first-time visitors to a detected or default locale, and keep slugs consistent across locales so links do not break. **Router-aware analytics.** Start analytics in a plugin and hook `router.afterEach` for pageviews. Define typed events like `signup_completed`, `checkout_started`, and `file_uploaded`. Queue events and flush on visibility change to reduce network noise. Respect privacy: do not send PII, and give users a settings toggle to opt out. For SSR, add a server hook that logs API-level events so you are not blind to server errors and cron results. **SEO defaults once, not everywhere.** Register sensible defaults for title, meta description, canonical URLs, and Open Graph. Expose a helper that merges per-page settings with defaults so each route sets only what is unique. Generate a sitemap at build time, include alternate language links, and reference it from robots.txt. Sanitize titles to a consistent pattern like `"Page Title · Product Name"`. **Source your blog and docs from Markdown.** Keep marketing and docs in the same repo without entangling them with app code. Expose a `$content.find` helper that returns Markdown, front-matter, and computed SEO tags. Render MD in a presentational component and map front-matter to `useHead` so writers control titles, descriptions, and og\:image without touching Vue files. **Catch errors with one reporting hook.** Install an error reporter in a plugin and capture client errors (`window.onerror`, `unhandledrejection`) and server exceptions. Attach user ID and plan after auth so you can see who hit what. Sample noisy errors and group by stack to keep alerts actionable. ## AI and marketplace integrations **Wrap AI chat and generation behind one client.** If you are asking how to build and sell an AI tool online, start by treating AI like any other vendor. Provide a single `$ai` client for chat, text, and image generation with a way to switch models by plan. Stream tokens to the UI, set timeouts and retries, and meter usage per user. Tie quotas to billing so free plans get daily caps and paid plans unlock faster models and higher limits. **Build marketplace helpers as a pluggable module.** If your app targets online sellers, unify marketplace actions like syncing orders, replying to messages, and generating invoices in one plugin. Use a queue-backed sync that pages through new orders, writes them idempotently, and emits UI events when work completes. For context on day-to-day workflows, this [operational guide to selling more on Mercado Libre](https://meliboost.com/blog/how-to/como-vender-mas-en-mercado-libre-tacticas-accionables/){rel=""dofollow""} covers software for Mercado Libre sellers to manage orders, messages, inventory, and CFDI invoicing. Let real workflows drive which endpoints you wrap first. ## When a Nuxt SaaS starter kit is the faster path There is a point where wiring plugins stops being leverage and starts delaying revenue. If you need authentication, protected pages, payments, i18n, admin, emails, files, analytics, SEO, AI calls, scheduled jobs, and a marketing site, you can either spend weeks integrating or start from a codebase that already solved it. Our Nuxt SaaS starter kit ships those pieces in a cohesive, typed codebase: authentication (email and password, magic links, Google), an admin panel to view users and ban abusers, provider-agnostic payments for one-time and subscriptions, multi-language with a visible switch, transactional emails with ready-to-edit templates, a preconfigured database with migrations, S3-compatible uploads, router-aware analytics, SEO defaults with an automatic sitemap, AI chat plus text and image generation with switchable models, scheduled cron jobs for digests and reminders, a Markdown-powered blog/docs setup, and a landing page you can customize by swapping copy. It plays well with AI coding tools like Cursor and Claude so you can iterate quickly without fighting your stack. Choose a starter kit when you are on a deadline, when billing accuracy matters more than custom architecture, or when your differentiation lives above the stack (workflow, UX, data). Keep plugins for app-specific logic, but do not hand-wire the fundamentals if your goal is to ship and learn from real customers. ### Key takeaways - Put cross-cutting behavior behind small, typed Nuxt plugins so pages and components stay simple. - Hide vendors you might swap later: payments, email, storage, analytics, and AI. - Tie AI usage to auth, plans, and quotas on day one to avoid messy retrofits. - When speed matters, a Nuxt SaaS starter kit gets you from idea to first sale faster than wiring everything by hand. ## FAQ ### What is a nuxt plugin and when should I create one? A nuxt plugin initializes or injects functionality that many parts of your app use. Create one when logic is shared across pages, like auth, analytics, or i18n. ### How do I load a nuxt plugin only on the client or only on the server? Place client-only code in a plugin with mode: 'client' or use filename.client. For server-only work, use a server plugin or Nitro plugin and avoid window or document. ### Can I swap payment providers without rewriting my UI? Yes, expose a small payments interface in a plugin and keep provider details in the implementation. Your components call the interface, not the vendor SDK. ### Is a starter kit faster than building plugins from scratch? If your timeline is short, a Nuxt SaaS starter kit is faster because core pieces like auth, payments, emails, and analytics already work end to end. ### How do I add AI chat and generation to my app safely? Wrap AI calls in a server route, inject a small client in a plugin, and tie access to plans and quotas. Log usage to avoid abuse and set clear limits. ## Recommended resources - [operational guide to selling more on Mercado Libre](https://meliboost.com) # Nuxt RBAC guide: roles, protected pages, and admin controls ![Practical Nuxt RBAC: model roles and permissions, guard routes and APIs, add admin guardrails and audits, and handle billing, auth, and export edge cases.](https://shipahe.ad/images/blog/nuxt-rbac-guide-roles-protected-pages-admin-controls/post-859.webp){style="max-width:100%;border-radius:12px"} You cannot fake access control. If your Nuxt app handles paid tiers, partner portals, or a back office, one missing permission check can expose data or hurt revenue. The goal is simple: one model for who can do what, enforced the same way on pages, APIs, and jobs. Here is a practical RBAC setup for Nuxt that holds up under growth, audits, and messy real-world behavior. ## Model roles and permissions Good RBAC starts with a small role set and an explicit permission catalog. Keep it boring and readable. If a teammate cannot reason about it in a code review, it will drift. ### Choose clear role names - Owner. Top-level authority within a workspace or account. Can change billing and assign roles. - Admin. Manages users and settings but cannot change ownership. - Member or Staff. Uses core features. Limited settings access. - Viewer or Read-only. Can view data but not update or export. - Guest. Minimal access for invitations or trials. Keep role names neutral. Actions belong in permissions, not labels. ### Write the permission catalog once List the verbs that matter to your product, then pair them with the nouns in your domain. Typical verbs: read, create, update, delete, export, bill, invite, manage\_roles. Pair with resources like project, dataset, invoice, report, model, file. This table is your source of truth for enforcement and tests. ### Represent it in code and the database Store the catalog in the database so you can adjust without redeploys. Mirror it in TypeScript for type safety. One workable approach with Prisma: ``` ``` Seed the base catalog once. Add a migration when you introduce a new feature that needs a permission. My rule of thumb: if you add an admin toggle for something, add a permission for it too. ## Enforce RBAC in Nuxt RBAC is only as strong as the checks on pages, APIs, and components. Apply the same decision function everywhere. ### A small, shared decision helper Put a single `can()` helper in a composable so templates, middleware, and server code call the same logic: ``` ``` Cache role membership in memory per request on the server so repeated checks are cheap, but always verify on the server before reading or writing sensitive data. ### Route meta and global middleware Declare required permissions on pages and enforce them in a single middleware: ``` ``` ``` ``` On SSR pages, this avoids flashing restricted content. Keep the meta terse and the middleware boring. ### Server validation every time Never rely on client checks. Re-evaluate permissions in every server handler that touches sensitive data: ``` ``` For file storage, check permission before generating signed URLs, and scope keys by tenant, for example `workspaces/{id}/files/{uuid}`. ### Component guards without UI leaks Hide or disable affordances that would lead to denied actions, and keep templates readable: ``` ``` Fetch role membership early in your auth flow so first paint matches the final state. ## Admin operations and auditability Human oversight is part of access control. You need a safe way to assign and revoke roles, respond to abuse, and explain what happened later. ### Assign and revoke with guardrails In the admin area, show current roles, the scope they apply to, and a change history. Add confirmation for risky actions like removing the last Owner from a workspace. Two simple protections stop most 2 a.m. tickets: - Block self-demotion if it would leave no Owner. - Enforce “at least one Owner” with a transaction that checks count before removal. ### Handle bans and suspensions Mix account state with RBAC. A banned user should be denied everywhere regardless of roles. Implement a fast pre-check in `can()` and mirror it on the server. ### Log what matters, not everything Log role changes, denied access, and sensitive operations like exports, deletes, billing changes, and permission edits. Keep payloads small and reference by ID to avoid personal data in logs. A compact event shape works well: ``` ``` Schedule a daily report of RBAC changes. The simplest path is a cron job that hits a Nuxt endpoint that aggregates yesterday’s events and emails a summary to your security or ops channel. ## Edge cases you must design for Most RBAC bugs hide in edges. Decide these now so they do not turn into breaches or churn. ### Multi-tenant scope is not optional Tie user roles to a scope like `workspace_id`. A user can be an Admin in one workspace and a Viewer in another. In server queries, always filter by both the tenant and the user’s scoped role. If you use Postgres, row-level security is worth the setup so you cannot forget the WHERE clause. ### Payments drive access Subscriptions often map to feature permissions. When a payment succeeds, grant or update the role; when a subscription ends, downgrade gracefully. Use one webhook handler that translates provider events into role changes and audit events. Make it idempotent with an events table so retries do not double-apply. ``` ``` Add a short grace period to handle provider delays so upgrades feel instant and downgrades are polite. ### Authentication quirks - Confirm email before granting roles to invited users. - Invalidate old sessions after role changes so access shrinks immediately. - Make magic links single-use and short-lived to block replay. - On social logins, link to existing accounts by verified email to avoid parallel accounts with different roles. ### Files and exports Exports and file downloads are sensitive. Check export permission when a job is created and again when the file is downloaded. Scope storage keys per-tenant and expire signed URLs quickly. Tools that process media for users, like SubtitlesFast, often gate higher-quality exports behind paid roles. Your Nuxt RBAC should mirror that pattern at both the job start and the download step. ### Owner lockout and recovery Protect the Owner role from accidental removal. Keep at least one Owner per workspace and add a recovery path through support that can restore ownership after proof of control. Document the process so support staff do not improvise access changes. If you want this all working on day one, start with a Nuxt/Vue boilerplate that already ships authentication, protected pages, admin, analytics, i18n, payments, email templates, and deployment tooling. Then your job is to fill the permission catalog and wire the checks, not reinvent sessions, webhooks, and cron wiring. ## Key takeaways - Keep a single permission catalog stored in the database and mirrored in TypeScript for compile-time checks. - Use route meta and global middleware to guard pages, and re-check permissions on every server handler. - Manage roles in an admin area with guardrails, bans, and clear change history. - Log role changes, denials, and sensitive operations; review daily with a simple cron-triggered report. - Design for edges: tenant scope, billing-driven access, auth quirks, export checks, and owner recovery. With a solid RBAC foundation, your Nuxt app grows cleanly, your team moves faster, and customers trust the boundaries you set. Whether you roll your own or start from a Nuxt SaaS boilerplate, keep the model simple, the checks consistent, and the audits boring. ## FAQ ### What is RBAC in a Nuxt app? RBAC assigns roles to users and grants permissions based on those roles. In Nuxt, you enforce it with route middleware, server checks, and an admin workflow. ### Should I store roles in the JWT or in the database? Store roles and permissions in the database as the source of truth. You can cache role IDs in a session token, but always verify on the server before allowing access. ### How do I connect subscriptions to RBAC? Map each plan to a role or set of permissions. On payment events, update the user’s role and log the change. On cancellation, downgrade after a brief grace period. ### How can I test RBAC in Nuxt? Write unit tests for your can(action, resource) helper, middleware tests for protected routes, and integration tests for server endpoints that read or write sensitive data. ### What is the safest way to handle owner transfers? Require confirmation from both parties, prevent removing the last owner, and record an audit entry. Provide a support-backed recovery path for edge cases. # Nuxt SaaS case study: from idea to $1,120 MRR in 30 days ![Two engineers hit $1,120 MRR in 30 days using a Nuxt SaaS starter kit with auth, payments, i18n, admin, SEO, and AI features, then iterated pricing to grow.](https://shipahe.ad/images/blog/nuxt-saas-case-study-first-1k-mrr-in-30-days/post-847.webp){style="max-width:100%;border-radius:12px"} You want to ship a paid AI tool fast, not spend your month on user tables and billing webhooks. This is our playbook. Two engineers, nights and weekends, took a clean Nuxt repo and turned it into a paid product doing $1,120 MRR in 30 days. The difference was choosing a Nuxt starter kit that already handled auth, payments, admin, i18n, analytics, SEO, and a launch-ready marketing site, so we could put almost all our time into the feature and pricing. ## Starting point and constraints Goal: validate a focused AI copy helper for small agencies and reach $1k+ MRR in the first month. Inputs: two engineers with Nuxt/Vue experience, a small email list of 1,800, and very little appetite for building plumbing. Definition of done: real users generating outputs, working subscriptions on two plans ($19 and $49), and a clean admin to keep spam out. We tracked three activation milestones from day one: time to first payment, percent of new users producing at least one output in 7 days, and MRR at day 30. We used the kit’s built-in analytics for events and funnels instead of wiring dashboards. ## Buy vs build: what we refused to code Our whiteboard list of non-negotiables looked like this. Estimated build times are from similar past projects: - Authentication (email, magic link, Google) with protected pages: 25 - 35 hours - Subscriptions, receipts, and webhooks with a switchable provider: 20 - 30 hours - Admin area for users, roles, and abuse controls: 12 - 18 hours - Database models, migrations, and a typed ORM: 10 - 15 hours - File storage for generated assets: 6 - 10 hours - Transactional emails (welcome, reset, receipts): 6 - 10 hours - SEO basics (sitemap, meta tags, Open Graph): 6 - 8 hours - Analytics and funnels: 6 - 8 hours - Marketing site with a solid landing page and blog: 10 - 15 hours Total: about 100 - 150 hours before touching the core feature. We bought a Nuxt boilerplate that shipped all of it and focused on the product. The kit gave us authentication with email/password, magic links, and Google sign-in, plus middleware to gate paid features. Checkout flows supported one-time and subscriptions. An admin panel let us review users, manage accounts, and ban spammers in minutes. It included a preconfigured database with an ORM and typed migrations, S3-compatible storage, transactional email templates, i18n with a language switcher, SEO automation for meta/OG/sitemap, built-in analytics, and a landing page we could rewrite without touching CSS. For the core feature, the kit’s AI utilities supported chat, text, and image generation with switchable models, which made cost-versus-quality tests trivial. We kept our stack boring and our time focused. ## Implementation timeline ### Days 1 - 3: Foundation and first output Day 1 was setup. We pulled the repo, set environment variables for app URL, database, storage bucket, and email provider, then ran initial migrations. We enabled email/password and Google sign-in, turned on middleware to protect app routes, and connected our payment provider through the kit’s config. We edited the landing page copy, pricing blocks, and hero image. Working shell in production: under 6 hours. Day 2 we wired a brief form to text generation: industry, goal, tone, and a content prompt. We added a developer-only switch to toggle the model and temperature for testing. Day 3 we added image generation for social banners, saved outputs to storage, and wrote a simple “generations” table to log user, input, tokens, and time. ### Days 4 - 7: Pricing, gating, and polish We created two subscription plans and mapped plan IDs to features. Advanced options were visible but disabled until sign-in, and exporting or saving outputs required an active subscription. We connected a usage counter to the ORM so each plan could have monthly credits without rework later. We customized transactional emails with clear sender details, plain subjects, and a single CTA: “Create your first output.” We set up meta tags and dynamic Open Graph images per route, and we published our first blog post using Nuxt Content to target phrases like nuxt starter kit and nuxt saas template. A couple of early posts did not index. RankGoat’s backlink building service includes a clear explainer, [Google indexing issues: diagnose and fix them fast](https://rankgoat.app/blog/indexing-issues-google-diagnose-fix-fast){rel=""dofollow""}, which helped us confirm sitemap submission, fix a canonical mismatch, and avoid blocking the content directory in robots.txt. Analytics events we tracked from the start: view\_home, sign\_up, first\_output, start\_checkout, and purchase\_completed. We built three funnels: home → signup, signup → first output, and first output → paid. A nightly cron emailed new users who had not created an output yet with a short tip and a direct link back to the brief form. ### Days 8 - 14: Private beta and i18n We invited 50 agency contacts. The admin panel made it easy to merge test accounts and ban obvious spam. Feedback asked for a Spanish UI. We enabled the language switcher and translated the top 20 strings in the app shell, brief form, and checkout. We also changed the default model to cut average generation cost by 23 percent without hurting quality, based on blind side-by-side samples. ### Days 15 - 21: Public launch We launched publicly with the refined landing page, two plans, a simple FAQ, and usage examples above the fold. We published two more blog posts and sent a focused announcement to our list. Analytics showed most signups came from the hero CTA and pricing section, so we resisted design churn and kept edits to copy and headings. ### Days 22 - 30: Smoothing friction We added a usage dashboard that shows credits, recent outputs, and upgrade prompts when users near limits. We trimmed checkout copy after seeing a drop-off between address and payment step. We updated transactional emails to link straight to saved drafts and added a weekly wrap email that surfaces high-performing outputs to re-engage light users. ## Launch metrics and MRR Time to first payment: 72 hours. Our first subscriber arrived on Day 4 and proved the path. Days 1 - 10 public: 2,320 unique visitors, 14 percent signup rate (325 accounts), 41 percent of signups produced at least one output, and 6 percent of signups converted to paid within 48 hours. That was 19 subscribers, split 12 on $19 and 7 on $49, for $601 MRR. Most traffic came from our list and social. The blog started contributing a small but steady trickle by Day 10 after we fixed indexing. Days 11 - 20: 3,100 more visitors, 11 percent signup rate (341), and 24 new subscribers. Tightening landing copy and simplifying checkout helped. Admin tools cut spam to near zero. Daily reminders increased first-output rates by 9 percentage points. By Day 30: 7,940 visits total, 1,020 signups, and 40 active subscribers split across 28 on $19 and 12 on $49. That is $1,120 MRR with minimal churn in month one. Analytics showed the Spanish UI drove 18 percent of new signups, which justified the early i18n work. Blog traffic reached 9 percent of total with almost no manual SEO work beyond publishing and keeping sitemap and canonicals correct. All of this happened without touching a custom analytics stack or hand-rolling auth. The Nuxt starter kit gave us rails so we could iterate on pricing, positioning, and prompts. ## Post-launch learnings - Ship rails, not scaffolding. Buying a Nuxt SaaS boilerplate that includes auth, protected pages, payments, admin, analytics, SEO automation, i18n, and a landing page converted multi-week chores into checkboxes. - Wire payments on day one. A working checkout in staging sharpens pricing and packaging. We tested annual vs. monthly and one-time add-ons without code churn. - Track activation with events you can change later. We used first\_output as the main early signal. When we saw a gap, we sent one helpful email and simplified the form, not five generic nudges. - Publish early and fix indexing fast. Automatic meta tags, OG images, and a sitemap are table stakes. The quick indexing check saved us from waiting a week to find a canonical issue. - Make i18n a fast follow. Translating the top 20 strings took hours and opened a second acquisition lane immediately. - Gating should be obvious. We let guests try the brief and see watermarked outputs, but saving, exporting, and advanced controls required a subscription. The contrast made the upgrade path clear without pop-ups. ### Key takeaways - 72 hours to the first payment because authentication, billing, and the landing page were already done. - $1,120 MRR by Day 30 from 40 subscribers across $19 and $49 plans. - Analytics events and simple funnels guided changes that lifted activation and reduced checkout drop-off. - SEO automation plus fast indexing fixes put the blog to work in week one. - Built-in AI utilities let us tune cost vs. quality and ship features users actually valued. ## FAQ ### What parts of the Nuxt starter kit saved the most time? Authentication, protected pages, subscription checkout, the admin panel, built-in analytics, SEO automation, and the prebuilt landing page cut weeks of setup. ### How fast can I accept payments with this Nuxt SaaS template? We connected a provider and tested live checkout within the first 24 hours, then took our first real payment on Day 4. ### Can I build and sell an AI tool online with this kit? Yes. It includes AI chat, text, and image generation with switchable GPT models, plus auth and subscriptions to gate and sell access. ### Does it support multi-language from day one? Yes. It ships with multi-language support and an in-app language switch, so you can add translations quickly. ### How did you track signups and conversions without extra tools? We used the kit’s built-in analytics to watch pageviews, signups, first outputs, and paid conversions, then adjusted copy and emails. ## Recommended resources - [Google indexing issues: diagnose and fix them fast](https://rankgoat.app) # Nuxt SaaS case study: launching an MVP in 10 days ![How we shipped a paid AI MVP in 10 days with a Nuxt starter kit. Real metrics on traffic, signups, conversions, revenue, and the exact features we used.](https://shipahe.ad/images/blog/nuxt-saas-case-study-launching-an-mvp-in-just-10-days/post-296.webp){style="max-width:100%;border-radius:12px"} You do not need a big team to ship a credible SaaS. You need a tight scope, a stack that removes decisions, and a plan to prove demand before energy runs out. This Nuxt SaaS case study shows how we shipped a paid AI MVP in 10 days, collected real revenue in 14 days, and avoided writing the parts every app repeats. ## Goals, constraints, and scope The brief: build a micro SaaS that turns messy customer notes into clean summaries with optional image snippets. We imposed two hard constraints. Timebox to 10 calendar days from repo to first paid user. Prove traction with numbers, not a demo. Launch targets for the first two weeks: - 1,000 unique visitors - 200 account signups - 25 paid conversions Scope pressure was real. We needed authentication, payments and checkout, an Admin Panel, analytics, SEO defaults, file uploads, multi-language support, and AI text plus image generation. Building that stack from scratch would consume the entire timeline. The guiding question became: how do I build and sell an AI tool online without rebuilding plumbing? Acceptance criteria were practical. First win under 5 minutes from signup. One pricing page. One onboarding flow. No custom design systems. No experimental features unless they directly lifted activation or conversion. ## Why a Nuxt starter kit and what we used We chose a Nuxt starter kit because server-rendered Vue with file-based routing and first-class content tooling fits the shape of a small SaaS. SSR gave us fast first paint and crawlable pages. Vue single-file components kept velocity high. Content collections made it easy to ship a landing page and one helpful post. We picked Shipahe.ad’s Nuxt boilerplate to avoid undifferentiated work. Out of the box we used: - User Authentication with email and Google. Sessions, password reset, and magic links were prebuilt with transactional email templates. - Payments and checkout for subscriptions and one-time credits. Success states and webhooks were scaffolded, so our work was pricing, copy, and testing. - An Admin Panel to view users, filter by plan or activity, and ban abusive accounts. Access control was already wired. - Multi-language support with an in-app language switch. Locale persisted per user and in URLs for SEO. - A type-safe database layer and migrations, plus S3-compatible file storage with signed URLs for uploads and downloads. - AI Generation Tools that let us call chat, text, and image models with a provider-agnostic interface. - Built-in Analytics for pageviews, signups, and custom events. No third-party pixels. - SEO automation for titles, descriptions, Open Graph images, and a sitemap. - A prebuilt landing page and a blog powered by Nuxt Content. - Cron job scaffolding for nightly tasks like cleanup and email nudges. Two operational choices increased speed further. We paired the kit’s AI coding workflow with Cursor to scaffold components and refactor quickly. We also kept the surface area small: one core workflow, one pricing page, one onboarding checklist. ## The 10-day build, day by day ### Days 1-2: Foundation without ceremony - Project created and environment variables wired in under 30 minutes. Local and staging envs used the same keys and .env layout to prevent “works on my machine” drift. - Authentication live on day 1. Email and Google login worked out of the box. We customized email templates and added rate limiting on auth endpoints. - Admin Panel online with search, plan filters, and manual bans. No need to build admin tables, pagination, or RBAC. ### Days 3-4: Payments and pricing - Configured subscriptions and a one-time credit pack. Webhooks for invoice.paid and charge.succeeded were pre-registered, so we focused on copy and testing downgrade and retry flows. - Kept the integration provider-agnostic. We launched with one provider and preserved the option to switch later by changing a single config and a small adapter. - Added basic usage limits per plan. Free users got 3 summaries and no images. Paid users got higher limits and priority processing. ### Days 5-6: Core AI and file handling - Implemented the main feature using the AI tools. Users pasted messy notes or uploaded a text file. We returned a structured summary with headings, bullets, and action items, and optionally generated a small illustrative image. - S3-compatible storage handled attachments with 15-minute signed URLs. We validated file type and size on both client and server. - Added nightly cron jobs: purge expired uploads, recalculate usage, and send a daily digest of new summaries to opted-in users. ### Day 7: Analytics, SEO, and content - Instrumented funnel events: signup\_submitted, onboarding\_completed, first\_summary, checkout\_started, checkout\_completed, and churn\_requested. - Verified SEO automation. We set default titles and descriptions, added canonical tags, checked OG and Twitter card previews, and generated the sitemap. - Shipped the landing page with focused copy and a single tutorial post to answer “who is this for” and “what does a good input look like.” ### Days 8-9: i18n, onboarding, and polish - Enabled English and Spanish with keyed UI strings. Locale choice persisted per user and in links for sharing. - Built a three-step onboarding checklist: upload a sample file, run a summary, and choose a plan. Admin shortcuts let support unblock stuck users fast. - Finalized transactional emails for welcome, password reset, and invoices. We kept them short, with plain language and a single next action. ### Day 10: Launch - Soft-launched to a small list and two communities. No discounts. We led with a 20-second screen recording that showed the first-win path. - Published a short changelog and opened a public feedback board. For prioritization, tools like Feedjolt help teams de-duplicate requests and decide what to build next without guesswork. ## Results: traffic, revenue, and ops ### Traffic and funnel - First 7 days after launch: 1,286 unique visitors. - Signups: 231 accounts created. Signup rate 17.9 percent of visitors. - Onboarding completion: 184 users ran at least one summary. Activation rate 79.6 percent of signups. - Paid conversions in 14 days: 31 new customers. Visitor-to-paid rate 2.4 percent. ### Revenue - Subscription plan plus a one-time credit pack. Revenue in the first 14 days totaled 1,480 USD. - 62 percent of revenue from subscriptions. 38 percent from one-time purchases. Refund rate 0 percent in the period. ### Ops and support - Average first-response time to support emails: 2 hours. Admin Panel shortcuts for user lookups and bans cut triage to minutes. - Nightly cron jobs sent an activation nudge to inactive signups. That email lifted day-2 activation by 11 percent. - Infra remained simple. One app cluster, object storage for uploads, and a single database. No service sprawl, no custom queues. ## Where the time actually went The kit removed whole categories of work. Here is what we would have spent building from scratch, compared to what we actually spent customizing the provided modules. - User Authentication. From-scratch estimate 2-3 days. Actual 0.5 day to style, configure providers, and add rate limits. - Payments and checkout. From-scratch estimate 3-4 days. Actual 1 day for pricing, copy, and flow tests including downgrades and failed renewals. - Admin Panel. From-scratch estimate 1-2 days. Actual 0.5 day to add search filters and quick actions. - File storage. From-scratch estimate 1 day. Actual 0.25 day to add validations and signed URL TTLs. - AI integration. From-scratch estimate 2 days to wire models and prompts. Actual 1 day to tune prompts and sanitize outputs. - Analytics. From-scratch estimate 0.5 day. Actual 0.1 day to confirm events and dashboards. - SEO. From-scratch estimate 0.5 day. Actual 0.1 day to validate tags and social previews. - i18n. From-scratch estimate 1 day. Actual 0.5 day to translate strings and test locale persistence. - Transactional emails. From-scratch estimate 1 day. Actual 0.25 day to edit templates and send tests. Conservatively, that is 10 to 14 engineering days saved. We reinvested those days in UX writing, pricing tests, and onboarding, which is where early traction usually lives. ## Lessons and a repeatable playbook ### What worked - Ship the boring parts pre-baked. Authentication, payments, admin, analytics, and SEO are not your edge. A Nuxt starter kit lets you spend time on the experience customers notice. - Own the funnel with built-in visibility. Instrument events at the app layer. Our biggest lift came from an activation nudge via cron and clearer upgrade copy. - Scope like a hawk. We cut anything that did not help a user succeed on day 1. One post, one page, one workflow. - Keep switching costs low. Provider-agnostic payments and swappable AI models protect you from fees or quality shifts later. - Content compounds. One tutorial that answered frequent questions now brings steady, qualified traffic for long-tail Nuxt SaaS queries. ### How to replicate in 10 days - Day 0: Write acceptance criteria. Define the first win, the single pricing page, and the activation event you will measure. - Day 1-2: Stand up auth and an Admin Panel. Add rate limits and support shortcuts early. - Day 3-4: Configure payments. Test success, failure, retries, upgrades, and downgrades. - Day 5-6: Build the core workflow end to end. Add minimal validation and guardrails. - Day 7: Instrument analytics, finalize SEO, and publish one helpful post. - Day 8-9: Add i18n for one secondary locale and a simple onboarding checklist. - Day 10: Launch to a targeted list. Collect feedback and ship one improvement per day. ### Key takeaways - A focused Nuxt starter kit can save 10 or more engineering days on an MVP. - Use built-in auth, payments, an Admin Panel, analytics, SEO, and file storage to keep your team on core value. - AI tools and model flexibility let you ship an AI MVP that feels complete on day 1. - Measure the funnel from the start and automate nudges with cron jobs. - Ask a simple question: what moves someone from first run to first win in under five minutes? If you are weighing a Nuxt boilerplate or a Vue Nuxt starter template and want to ship fast, treat this as your checklist. Pick the smallest surface that can make money, choose a Nuxt boilerplate that includes the boring parts, and invest your energy where it counts. # Nuxt SEO Best Practices – How to Get Your SaaS Ranked in 2026 You can build the best SaaS in the world, but if you're invisible on Google, you don't have a business. For solo founders, organic traffic is the ultimate leverage. It’s consistent, high-converting, and—most importantly—free. Nuxt is already a beast for SEO thanks to Server-Side Rendering (SSR). But out-of-the-box performance isn't enough to beat the competition in 2026. Here is the exact SEO checklist I use for every Nuxt project to ensure it actually ranks. --- ## 1. Dynamic Metadata Management Google uses your Page Title and Meta Description to understand what your page is about. If these are missing or generic, you won't rank. In Nuxt, you should use the `useHead` or `useSeoMeta` composable. **The Golden Rules for Metadata:** - **Title:** Under 60 characters. Place your primary keyword at the beginning. - **Description:** Under 155 characters. Include a call to action (e.g., "Try for free"). ```typescript useSeoMeta({ title: 'Optimize Your SaaS for SEO in 5 Minutes | ShipAhead', ogTitle: 'Optimize Your SaaS for SEO in 5 Minutes', description: 'Learn the exact Nuxt SEO best practices used by successful founders to reach page one of Google.', ogDescription: 'Learn the exact Nuxt SEO best practices used by successful founders to reach page one of Google.', ogImage: 'https://shipahe.ad/og-image.png', twitterCard: 'summary_large_image', }); ``` --- ## 2. Structural Hierarchy (H1 to H6) Google's crawlers read your page like a book. Your H1 tag is the book title. Every page must have exactly **one** H1 tag that contains your main keyword. **Bad Heading:** "Our Platform Helps You Build" (Vague) **Good Heading:** "Build and Launch Your SaaS in 7 Days" (Benefit-driven and keyword-rich) Use H2 and H3 tags to break up your content into logical sections. This makes it easier for both Google and humans to skim your site. --- ## 3. Automated Sitemaps and Robots.txt You want to make it as easy as possible for Google to find every corner of your site. - **Sitemap:** Use the `@nuxtjs/sitemap` module. It automatically generates a list of all your pages so Google never misses an update. - **Clean URLs:** Ensure your slugs are descriptive. For example, `/blog/nuxt-seo-best-practices` is much more valuable than `/post/12345`. --- ## 4. Boost Ranking with Structured Data (JSON-LD) Structured data tells Google specifically what kind of content you have. For a SaaS, you should use "SoftwareApplication" schema. This can lead to "rich snippets" in search results, like showing your pricing or star ratings directly on the Google search page. --- ## 5. Prioritize Page Speed (Core Web Vitals) Google explicitly ranks faster sites higher. **Search engine optimization for startups** often starts with performance. - **Optimize Images:** Use the `nuxt-img` component to serve WebP images that are 80% smaller than JPEGs. - **Server-Side Rendering:** Always use `ssr: true` (the default) to ensure Google can see your content immediately without waiting for JavaScript to load. By starting with a foundation like [ShipAhead](https://shipahe.ad){rel=""nofollow""}, you get these performance optimizations out of the box. --- ## 6. Internal Linking Strategy Don't let your pages be "islands." If you write a blog post, link back to your home page and your features page. This "spreads the juice" and helps Google understand which pages are the most important. --- ## 7. The Power of Content Marketing The best way to get traffic is to provide value. Start a blog and answer the questions your customers are asking. If someone searches for "How to take payments in Nuxt" and finds your guide, they are 10x more likely to buy your Nuxt starter kit. This is the secret to sustainable, long-term growth. --- ## Final Thoughts SEO is a marathon, not a sprint. By implementing these **Nuxt SEO best practices**, you are building an asset that will bring you customers for years to come. Ready to build an SEO-optimized SaaS? Get [ShipAhead](https://shipahe.ad){rel=""nofollow""} and hit the ground running with a search-ready foundation. # Nuxt Stripe payments for one-time and subscription billing ![Set up Stripe payments in Nuxt: one-time checkout, subscriptions, trials, webhooks, testing, and launch steps with concrete examples you can ship today.](https://shipahe.ad/images/blog/nuxt-stripe-payments-for-one-time-and-subscription-billing/post-496.webp){style="max-width:100%;border-radius:12px"} You want to accept money in your Nuxt app without duct-taping code together. Stripe is a solid choice, but mixing one-time purchases, subscriptions, trials, and the webhook glue gets confusing fast. This guide gives you a clear, repeatable pattern for Nuxt Stripe payments that you can put in production. We will use Stripe Checkout because it is quick to implement, handles Strong Customer Authentication, and works for both one-time and recurring billing. The same structure applies whether you are selling a small digital product, an AI tool, or a full SaaS. ## 1) Choose your payment flow ### Pick a product model - One-time purchase. A single payment that unlocks a file, feature, or credit pack. Good for add-ons and downloadable assets. - Subscription. Recurring billing tied to plans. Add free trials or intro pricing if needed. Good for SaaS tiers and usage that resets monthly. - Hybrid. Mix both. For example, a monthly plan plus a one-time add-on that boosts limits. If you are building something like CoinDrop, you might sell a monthly tier and let users buy a one-time boost for a promotion. ### Choose Stripe primitives - Define Products and Prices in the Stripe Dashboard. Use one-time prices for single charges and recurring prices for subscriptions. - Use Stripe Checkout for the hosted payment page. Always create the Checkout Session on your server and redirect the browser to it. This keeps PCI scope low and handles 3D Secure. - Use Webhooks to confirm payment and flip access in your app. Do not grant entitlements on a client-only success page. - Create a Stripe Customer for each user and store customer\_id on your User row. That makes upgrades, refunds, and future purchases consistent. ## 2) One-time payments with Stripe Checkout Your flow: user clicks Buy, your server creates a Checkout Session with mode set to payment, Stripe collects the card, Stripe pings your webhook, and your app grants access. 1. **Define the catalog.** In Stripe, create a Product with a one-time Price. Record the price\_id in your app config. Keep an allowlist of valid price ids on the server. 2. **Server route to create a session.** In Nuxt 3, add a POST route like /api/checkout that validates input, attaches user metadata, and returns session.url. Include success and cancel URLs that route back to your app. ``` ``` 3. **Redirect from the client.** On your product page, call /api/checkout and redirect to the returned URL. Keep the UI clean. One Buy button, a short explainer, and a price. 4. **Flip access on webhook, not on the success page.** In your webhook handler, verify the signature and on checkout.session.completed mark the purchase as paid. Create a Purchase row that includes payment\_intent id, user\_id from metadata, and the product key. Grant access by inserting a record into a UserEntitlements table or toggling a feature flag. ``` ``` 5. **Send receipts.** Stripe can send receipts automatically. If you send your own email, include a link to the protected page or download, and a VAT invoice link if you collect tax IDs. 6. **Protect the content.** Gate access server-side. For downloads, generate a short-lived signed URL after you confirm the paid Purchase record. ## 3) Subscriptions and trials Subscriptions add lifecycle events. Plan for upgrades, downgrades, renewals, cancellations, and expired trials. Stripe Checkout creates the subscription and emits consistent events you can trust. 1. **Create recurring prices.** In Stripe, set up monthly or yearly Prices. If you want a trial, either set a trial period on the Price or set trial\_end when creating the Checkout Session to control the exact date. 2. **Subscription checkout route.** Similar to one-time, but set mode to subscription and pass the recurring price id. Keep a server-side allowlist of tier price ids, and add user\_id and plan to metadata. ``` ``` 3. **Persist the subscription.** On checkout.session.completed, read session.subscription to get the subscription id. Store a Subscription row with status active, current\_period\_end, plan id, and the Stripe customer id. Use invoice.paid to extend access and invoice.payment\_failed to start dunning with a short grace period. 4. **Upgrades and downgrades.** For upgrades mid-cycle, update the subscription item with proration\_behavior set to create\_prorations so users pay the difference. For downgrades, schedule the change at period end and reflect it in your UI with a plan\_change\_requested flag. 5. **Cancellations and trials.** On customer.subscription.updated or deleted, sync status to past\_due, canceled, or paused. If a trial ends without payment, remove entitlements when the subscription becomes incomplete\_expired. ## 4) Webhooks, testing, and launch ### Webhook fundamentals - **Verify signatures.** Use the signing secret from your Stripe Dashboard. Reject any event that fails verification. - **Idempotency and retries.** Store processed event ids. Stripe retries on failures and timeouts. Make handlers side-effect safe. - **Map events to users.** Put your internal user\_id into Checkout Session metadata or into the Customer object. Do not rely on email lookups that can change. - **Choose the right events.** For one-time, rely on checkout.session.completed. For subscriptions, also listen to invoice.paid, invoice.payment\_failed, customer.subscription.updated, and customer.subscription.deleted. Handle charge.refunded to revoke one-time access when needed. ### Receipts and emails - **Stripe receipts.** Turn on email receipts in Stripe for payment confirmations and refunds. - **Your transactional emails.** Send welcomes, payment confirmations, dunning messages, and cancellation notices from your app. Include a Manage billing link in your account area. ### Testing - **Use test keys and env vars.** Keep STRIPE\_SECRET\_KEY and STRIPE\_WEBHOOK\_SECRET in .env. Never mix test and live data. - **Test 3D Secure and failures.** Use Stripe’s test cards to cover success, authentication required, insufficient funds, and generic declines. Verify your UI messages. - **Run webhooks locally.** Use the Stripe CLI to forward events to your machine: stripe listen --forward-to localhost:3000/api/stripe-webhook. Replay an event to confirm idempotency. - **Validate entitlements.** After each test purchase, check database rows and confirm protected pages are gated. Revoke access and test again to catch race conditions. - **Refunds and disputes.** Add a simple admin action to refund and revoke access. For subscriptions, document whether you prorate on mid-cycle refunds. - **Go live safely.** Switch production to live keys, set the live webhook signing secret, and verify success\_url and cancel\_url use your live domain. Run a small live charge on your own card to sanity check. ### Where a Nuxt SaaS starter kit helps If you want to ship fast, a solid Nuxt SaaS starter kit cuts weeks from setup. Shipahe.ad includes authentication, protected pages for paid features, subscription and one-time checkout flows, webhooks wired to entitlements, transactional emails, an admin panel to view users and ban spammers, multi-language support with an in-app switch, deployment presets, a prebuilt landing page you can customize, built-in analytics to watch signups and conversions, and SEO automation for meta tags and sitemaps. It also works cleanly with AI coding tools like Cursor or Claude, which helps you write server routes and handlers faster without fighting the stack. ## Key takeaways - Stripe Checkout plus webhooks is the fastest, reliable path for Nuxt Stripe payments across one-time and subscriptions. - Model entitlements in your database and flip them only on verified webhook events, not on client redirects. - Keep a Stripe customer\_id on each user and an allowlist of price ids on the server. - Test every branch in test mode, including authentication-required flows and failures, before going live. - A Nuxt starter kit with payments, protected pages, emails, and admin removes setup friction so you can focus on your product. # Nuxt test-utils: setup, examples, and testing patterns ![Set up nuxt test-utils with Vitest, write component, server, and browser tests for Nuxt 3, and avoid flaky suites with clear, concrete patterns.](https://shipahe.ad/images/blog/nuxt-test-utils-setup-examples-best-practices/post-744.webp){style="max-width:100%;border-radius:12px"} You can ship a Nuxt app fast, then lose days chasing regressions because one prop changed or a route moved. Good tests pay you back on every deploy. nuxt test-utils gives you a Nuxt-aware test environment so you can validate components, composables, server routes, and pages with real confidence. My rule for SaaS and AI tools: test what earns or protects revenue first. That means signup, login, checkout, webhooks, locale routing, and admin permission checks. Then cover the glue code you are afraid to touch. If you are weighing a Nuxt starter kit or a Nuxt SaaS boilerplate to ship fast, put testing in the plan from day one. That is true whether you are building a small dashboard, a subscription app, or asking yourself, how do I build and sell an AI tool online? ## What nuxt test-utils actually provides nuxt test-utils boots a real Nuxt context inside Vitest. Your auto-imports, runtime config, plugins, middleware, and the Nitro server behave like they do in dev. Concretely, you can: - Mount Vue components with Nuxt plugins and auto-imports available using `mountSuspended`. Async setup and Suspense are resolved before assertions. - Call server routes with `$fetch` against a live Nitro instance that starts once for your suite. - Open a browser page for lightweight end-to-end checks with `createPage` (Playwright under the hood). It complements `@vue/test-utils` for deep component interactions and Playwright for full-browser automation. You get fast unit and integration feedback without wiring a custom server by hand. ## Set up nuxt test-utils with Vitest (step by step) 1. **Install dev dependencies.** `npm i -D vitest nuxt-vitest @nuxt/test-utils @vue/test-utils` 2. **Enable the Vitest module.** In `nuxt.config.ts` add `modules: ['nuxt-vitest']`. If you need test-only config, set `test` keys inside `runtimeConfig`. 3. **Create a Vitest config.** In `vitest.config.ts`: `export default defineConfig({ test: { environment: 'nuxt', globals: true, setupFiles: ['./tests/setup.ts'] } })`. The setup file is optional but handy for `mockNuxtImport` and test-wide hooks. 4. **Add a first test.** Create `tests/components/Counter.spec.ts`. Example: `const wrapper = await mountSuspended(Counter); await wrapper.get('button').trigger('click'); expect(wrapper.text()).toContain('1')`. 5. **Run tests.** `npx vitest` for watch mode, or `npx vitest --run` in CI. If you will use `createPage`, run `npx playwright install` once. That is enough to mount components with a live Nuxt context and to hit server routes in tests. ## Write tests that cover real Nuxt behavior ### 1) Components: mount with Nuxt context Use `mountSuspended` from `@nuxt/test-utils/runtime` so async setup and Suspense complete before assertions. This avoids race conditions that appear with a plain Vue mount. - **Mount with props.** `const wrapper = await mountSuspended(MyButton, { props: { label: 'Pay now' } })`. - **Assert DOM and events.** `await wrapper.get('button').trigger('click')` then `expect(wrapper.emitted('click')).toBeTruthy()`. - **Provide plugins or mocks.** Pass `global.plugins` (e.g., your i18n instance) or `global.mocks` for injected keys. - **Router-aware UI.** If the component reads route params, mock them: `mockNuxtImport('useRoute', () => () => ({ params: { id: '42' }, query: {} }))`. Tip: If your component reads `useRuntimeConfig()`, do not hand-roll a stub. Prefer setting `runtimeConfig` for the test environment in `nuxt.config.ts`, or mock the import with `mockNuxtImport('useRuntimeConfig', ...)` for a single spec. ### 2) Composables: isolate logic, mock Nuxt imports Composables often call `useFetch`, `useState`, or `useRuntimeConfig`. Mock those auto-imports so unit tests never hit the network. - **Mock a runtime value.** `mockNuxtImport('useRuntimeConfig', () => () => ({ public: { apiBase: '/api' } }))`. - **Mock `useFetch` with reactive results.** `mockNuxtImport('useFetch', () => async () => ({ data: { value: { ok: true } }, pending: { value: false }, error: { value: null } }))`. Return refs for `data`, `pending`, and `error` to match real behavior. - **Exercise branches.** Write one test for success, one for `error`, one for `pending`. Add a case for 401 to confirm your refresh or logout path. Run the composable inside a tiny component with `mountSuspended`, or export pure helpers for direct testing. ### 3) Server routes: call Nitro with `$fetch` Start Nitro once at the suite level, then hit endpoints with `$fetch`. You get real middleware, auth checks, and runtime config. - **Boot the test context.** `import { setup, $fetch } from '@nuxt/test-utils'` and `await setup({})` in `tests/setup.ts`. - **Call endpoints.** `const res = await $fetch('/api/health')`; assert status and JSON shape. - **Seed data.** Prepare rows in a test database in `beforeEach`, clean up in `afterEach`. Use an isolated schema or an in-memory DB to avoid cross-test bleed. - **Auth headers.** For cookie auth, pass `headers: { cookie: 'session=...' }`. For token auth, set `authorization: 'Bearer '` and assert 401/403 on bad tokens. For apps with webhooks or subscription billing, route tests catch mistakes that unit tests miss, like missing auth headers or wrong JSON. If you run a tool like MeliBoost, you know how many tiny flows can break if you do not guard them. ### 4) Pages and middleware: browser checks with `createPage` For a quick smoke test, open a page in a real browser context. - **Enable the browser.** `await setup({ browser: true })`. - **Open a page.** `const page = await createPage('/')`, then `await page.locator('h1').waitFor()`. - **Assert UI.** Use stable selectors: `await expect(await page.textContent('[data-testid="title"]')).toContain('Dashboard')`. Keep these short. Use them to catch routing, middleware, or rendering errors, not to click through your whole app. Put full flows in a separate Playwright suite if you need them. ## Fit testing into a Nuxt SaaS workflow If you start from a Nuxt SaaS starter kit or a Vue/Nuxt starter template, you already have authentication, protected pages, checkout, i18n, and a landing page. Test those building blocks first because they move most during early changes. - **Authentication and protected routes.** Unit: stub the session or token and verify guards render the right state. Server: assert 401 for unauthenticated requests and 200 for valid cookies on a sample protected route. - **Payments and checkout.** Use provider test mode or your mock server. Assert idempotency on retries, subscription status transitions, and error branches (insufficient funds, canceled checkout, expired webhook signature). - **i18n.** Mount with at least two locales. Assert a few high-value keys render and that the locale switcher updates route and head tags. - **SEO and `useSeoMeta`.** For critical pages, assert a non-empty ``, canonical URL where applicable, and language meta when locale changes. - **Admin roles.** Verify role-based middleware blocks non-admins and hides admin-only UI controls. Practical structure that scales: - `tests/components` for isolated UI - `tests/composables` for logic - `tests/server` for Nitro routes and webhooks - `tests/browser` for a handful of smoke tests Add tiny helpers that pay off quickly: `loginAs(user)` to set a cookie in tests, `factory({ table: 'users' })` to create rows, and `withLocale(locale, fn)` to swap language during a spec. ## Pitfalls and CI without flakes - **Tests hang on Suspense.** Use `mountSuspended`, await the mount, and avoid triggering async work after assertions. - **Auto-imports not found.** Ensure `environment: 'nuxt'` in `vitest.config.ts` and `modules: ['nuxt-vitest']` in `nuxt.config.ts`. - **Network calls in unit tests.** Mock `useFetch` or your HTTP client. Keep real calls in server route tests with `$fetch`. - **Stale Nitro state.** If a test needs a fresh server, isolate it in its own file or reset state in `afterEach`. Prefer stateless handlers. - **Playwright missing.** If `createPage` fails, run `npx playwright install` and rerun the suite. - **ESM/TypeScript hiccups.** Align `tsconfig.json` with Nuxt defaults. Avoid CJS-only libraries in ESM tests. - **Pin execution in CI.** Use the same Node version locally and in CI. Cache Playwright browsers to speed up runs. - **One command.** Add `"test": "vitest --run"` to `package.json`. Add `--reporter=junit` if CI expects JUnit XML. - **Seed and isolate data.** Run migrations before the suite, use a separate test database, and clean up per test. Parallel runs should not share state. - **Coverage that matters.** Enable `coverage` in `vitest.config.ts`. Focus on paths that guard money, like signup and checkout, not every branch of a spinner component. ## Key takeaways - nuxt test-utils runs a real Nuxt context inside Vitest so your tests mirror production behavior. - Use `mountSuspended` for components, `$fetch` for server routes, and `createPage` for quick browser checks. - Mock Nuxt auto-imports in composable tests to avoid network calls and flakes. - Prioritize auth, protected pages, payments, and locale routing in a Nuxt SaaS template. - Keep browser tests short; let unit and integration tests carry most coverage. If you already work from a Nuxt SaaS template or a Nuxt SaaS starter kit, plug these patterns in now. They will keep you shipping without fear when features like authentication, payments, multi-language support, admin tools, transactional emails, analytics, and SEO settings start to change. ## FAQ ### What is the difference between nuxt test-utils and @vue/test-utils? nuxt test-utils boots a Nuxt-aware test environment and Nitro server. @vue/test-utils mounts Vue components. Use them together to test Nuxt components with real context. ### How do I test a Nuxt server route with Vitest? Call setup from @nuxt/test-utils, then use $fetch to hit your endpoint. Seed any required data before the request and assert the response shape. ### Do I need Playwright to use createPage? Yes. createPage relies on Playwright. Install it once with npx playwright install, then you can open real pages in tests. ### How can I mock useFetch in a composable test? Use mockNuxtImport from nuxt-vitest/utils to stub useFetch and return a predictable data value, pending state, and error. ### Should I still write tests if I use a Nuxt SaaS starter kit? Yes. A starter kit helps you ship fast, but tests protect key flows like auth, checkout, and i18n when you start changing code. # nuxt/test-utils: Practical testing for Nuxt 3 SaaS apps ![Set up nuxt/test-utils with Vitest to test pages, APIs, auth, i18n, and payments in Nuxt 3. Real examples, CI tips, and pitfalls to ship with confidence.](https://shipahe.ad/images/blog/nuxt-test-utils-step-by-step-guide-testing-nuxt-3/post-738.webp){style="max-width:100%;border-radius:12px"} You can bolt together pages, APIs, and auth in Nuxt 3 fast. Shipping without tests is still a coin flip. If you are here for a production-like test setup, this is how we use nuxt/test-utils to verify the exact flows a SaaS depends on before we deploy. ## What nuxt/test-utils actually gives you nuxt/test-utils boots a real Nuxt instance in your test runner. Your tests hit Nitro routes, render pages, resolve auto-imported composables, run route middleware, and load modules like i18n the same way they do in production. You get: - Server-level tests with `$fetch` that return HTML or JSON from real routes. - Component tests with a Nuxt-aware mount so plugins, runtime config, and route context work. - Helpers to mock Nuxt imports and composables without rewriting your app. This is the right layer for cross-cutting SaaS features: protected pages, multi-tenant or i18n routing, payments and webhooks, an admin area, file storage, and cron-driven emails. A unit test will not catch a broken redirect or a missing `Content-Language` header. A nuxt/test-utils run will. ## Set up a production-like test rig Use Vitest as the runner, node as the default environment for server tests, and jsdom for DOM-heavy component tests. 1. **Install deps.** ``` ``` 2. **Vitest config.** Keep server tests fast by default. ``` ``` 3. **Spin up Nuxt inside tests.** Start in dev mode locally for speed. Use build mode in CI to catch production-only issues. ``` ``` :brCI switch: ``` ``` 4. **Test a real server route.** ``` ``` 5. **Mock Nuxt imports for app behavior.** Replace composables like auth and runtime config. ``` ``` 6. **Component tests with Nuxt context.** Use a Nuxt-aware mount so plugins and route meta resolve. ``` ``` 7. **Stable data and time.** Reset the database and freeze time for repeatable assertions. ``` ``` ## Cover the money-making flows first Target the paths that turn visitors into revenue and support. We keep two tests per protected page, one for anonymous, one for signed-in, then extend that pattern across billing, i18n, and admin. - **Protected pages and authentication.** Mock an anonymous user and assert a redirect to login with a preserved return URL. Then mock a valid session from any provider you support and assert the page renders the same post-login state. This catches middleware drift when you add a new provider. - **Payments and checkout.** Your checkout route should return a payment URL or client secret and respect plan and billing interval. For webhooks, stub signature verification and assert the state change, not the provider API. Example: ``` ``` - **Language switching and SEO.** Fetch the same page under two locales and assert visible text, `<title>`, `metaname=description`, `htmllang`, and canonical or `hreflang` tags all switch. Also hit `/sitemap.xml` and ensure core URLs exist for each supported locale. - **Admin area and RBAC.** Mock a regular user and expect a 403 or redirect. Mock an admin and assert the dashboard renders and that actions like banning a user return the right status code and audit entry. - **AI features and uploads.** Stub your model client so each request is called exactly once with sanitized inputs. For S3-compatible storage, replace the SDK with a fake adapter and assert files land in the expected bucket and signed URLs expire when intended. - **Cron jobs and transactional emails.** Trigger your scheduled handler with a fixed date. Assert the right jobs are queued. For password resets and welcomes, verify your code enqueues the correct template with the right variables. Do not test the email provider. ## Keep CI fast and reliable - **Split suites.** Run a tiny smoke set in dev mode locally on save. Run a stricter build-mode suite in CI. - **Mock the edges, not the middle.** Stub payment, email, AI, and storage SDKs. Leave your routing, middleware, and rendering real. - **Reset between tests.** Clear DB tables, cookies, and any global mocks or mutated runtime config in `afterEach`. - **Hydration-aware checks.** If a component renders only on the client, use a Nuxt-aware mount and wait for the element that proves hydration completed before asserting. - **Lock the environment.** Use a dedicated `.env.test`, pin Node in CI, and commit your lockfile. Differences here cause the passes locally, fails in CI pattern. - **Verify assets once in build mode.** Fetch a page that includes images or fonts and then request one referenced asset URL. Expect a 200 to catch public path mistakes. ## Key takeaways - Boot a real Nuxt instance with nuxt/test-utils so you test pages and APIs the way users hit them. - Start with a smoke test, then cover auth, payments, i18n, and admin access end to end. - Run fast dev-mode tests locally and a build-mode suite in CI. Stub external services but keep routing and rendering real. - Assert user-visible outcomes and stable side effects, not internal call stacks. If your SaaS includes a blog and you want launch content that compounds, this [SEO content calendar template](https://rankgoat.app/blog/seo-content-calendar-template-plan-a-month-of-posts-fast){rel=""dofollow""} shows how to plan four weeks of posts in about an hour and pairs well with a backlink building service that secures dofollow links and fixes indexing so posts start pulling traffic. Working inside a Nuxt SaaS starter kit means you begin with known patterns for auth, payments, i18n, admin, and deployment. Add the tests above on day one and you can ship faster without trading away quality. ## FAQ ### Does nuxt/test-utils work with Vitest or Jest? Use Vitest. nuxt/test-utils is designed to run smoothly with Vitest for Nuxt 3 projects and gives you helpers to boot a Nuxt instance during tests. ### Should I run tests in dev mode or after building the app? Use dev mode for fast feedback while coding and build mode in CI to catch production-only issues like asset paths and Nitro routing differences. ### How do I test protected pages that require login? Mock your auth composable to simulate a signed-in or anonymous user, then fetch the protected route and assert on either the rendered page or the redirect. ### How can I test i18n in a Nuxt app? Fetch the same page under two locales and assert changes to visible text and meta tags. Provide a minimal translation dictionary in your test context. ### What should I mock for payments and emails? Mock the payment provider SDK and email sender. Assert your code sends the correct inputs and updates state. Do not call real external services in tests. ## Recommended resources - [SEO content calendar template](https://rankgoat.app) # Nuxt vs Vue: How to Choose, Set Up, and Ship Fast Today ![Nuxt vs Vue with concrete steps, quickstarts, SSR gotchas to avoid, and how a Nuxt SaaS starter kit helps you launch paid features and rank faster.](https://shipahe.ad/images/blog/nuxt-vs-vue-how-to-choose-set-up-and-ship-fast-today/post-715.webp){style="max-width:100%;border-radius:12px"} You want your first paid users, not a month of wiring. The Nuxt vs Vue choice decides how many decisions you make later and how fast you get to a protected, paid slice. Here is a clear way to choose, set up both, and avoid the traps that slow down SaaS launches. ## What Nuxt vs Vue actually means Vue is the UI layer. It gives you components, reactivity, and a client-side app by default. You assemble routing, state, meta tags, data fetching, and any server piece yourself. That flexibility is great for small SPAs and embed widgets, but it means more glue when you need SEO, auth, and payments. Nuxt is a full-stack framework built on Vue. It adds file-based routing, a server runtime via Nitro, first-class SSR and static generation, server routes in *server/api*, auto-imported composables, meta and SEO helpers, and an opinionated structure. You can pick rendering per route, share types between client and server, and deploy to Node or serverless. For SaaS work where you need public pages that rank and an authenticated app that just works, Nuxt removes a lot of decisions. In practice: choose Vue for a small SPA or widget where SEO does not matter and a static host is enough. Choose Nuxt when you need marketing pages to index, fast first paint, server endpoints for auth, webhooks, and payments, or a predictable structure for a growing app. ## How to decide in 5 concrete steps 1. **List non-negotiables.** Write down must-haves for v1. Common SaaS needs: public landing and pricing pages, user dashboard, authentication, protected routes, subscription billing, multi-language, transactional email, analytics, file uploads, cron jobs, and maybe an AI chat or generator. If public pages need to be fast and indexable on day one, lean Nuxt. 2. **Pick a rendering model per page type.** Map pages to rendering early. Examples: */*, */pricing*, */blog* as SSR or static; */app* dashboards as client-first; */docs* as static with incremental rebuilds. With Vue alone you stay client-only unless you bolt on SSR or SSG. With Nuxt you can mix SSR, SSG, and client-only per route without extra tooling. 3. **Decide how much glue code you want.** Vue means choosing and wiring `vue-router`, state (often Pinia), a head manager, an HTTP layer, and an SSR or SSG approach if you need SEO. Nuxt ships file-based routes, Pinia integration, `useHead`, `useFetch`/`useAsyncData`, runtime config, and server routes. If the goal is a working paid slice this week, Nuxt reduces integrations and edge-case bugs. 4. **Plan hosting and deployment.** Pure Vue SPAs work on any static host. Nuxt 3 apps can deploy to Node servers or serverless. Check your provider supports Node 18+ and the Nuxt server runtime. If you need server routes for webhooks or payments, Nuxt’s *server* directory keeps everything in one repo. 5. **Timebox a spike in both.** Spin up a Vue project and a Nuxt project. Implement one public page with a meta description, one protected route, and a mock subscription check. Ship whichever stack gets you there cleaner and faster. ## Quickstart: set up Nuxt and Vue side by side ### Nuxt quickstart 1. **Create the project.** ``` ``` 2. **Add a page.** Create *pages/index.vue*. Nuxt routes it automatically. ``` ``` :br 3. **Create a server route.** Add *server/api/ping.get.ts* for a simple health check. ``` ``` 4. **Fetch data safely.** Use `useAsyncData` to call your API with SSR support. ``` ``` :br 5. **Choose rendering per route.** Mark pages client-only or pre-rendered. ``` ``` ``` ``` 6. **Guard analytics and browser-only code.** Put browser-only plugins in *plugins/analytics.client.ts* so they never run on the server. Wrap window access in client checks or the built-in component below. ``` ``` ### Vue quickstart 1. **Create the project.** ``` ``` 2. **Add routing.** Install and configure Vue Router. ``` ``` ``` ``` :br 3. **Set document titles.** Use a head manager or set titles in `onMounted`. Full SEO requires SSR or prerendering through an additional tool. Without that, new sites often see weak indexing. 4. **Add a protected view.** Gate routes with a navigation guard that checks auth, then wire a backend or serverless functions for login and APIs. ``` ``` ## Ship faster with a Nuxt SaaS starter kit If your goal is to make your first dollars online, a production-ready Nuxt SaaS starter kit trades setup work for product work. A solid kit typically ships with: - Authentication: email and password, magic links, social sign-in, session handling on server routes, and secure cookies. - Payments: subscription and one-time charges, webhook processors, subscription state synced to your database, and a billing portal link. - Internationalization: locale switcher, per-locale routes like */en* and */fr*, message loading rules, and SEO-safe defaults. - Transactional email: password resets, welcomes, receipts, and templating with environment-based providers. - Admin: user list, role management, ban and unban, and audit logs. - Content: a blog or docs with Markdown, slugs, sitemaps, and Open Graph images. - Developer experience: a typed codebase, ESLint, formatting, unit and e2e tests, environment switch, and example CI. - File uploads: S3-compatible direct uploads with signed URLs, image processing hooks, and storage keys saved in the database. - AI features: chat and text generation wired to a provider, with model swapping in config. Buying a Nuxt boilerplate is not skipping learning. It is concentrating your time on differentiating features. If you want to buy a Nuxt boilerplate or a Vue Nuxt starter template, pick one that matches your payment provider, database, and auth model so you do not fight the foundation later. ## Common pitfalls and how to avoid them - **Mismatched rendering.** Hydration errors like "Text content does not match" happen when a component relies on `window` or browser-only APIs during SSR. In Nuxt, wrap browser-only code with `<ClientOnly>` or guard with `if (process.client)`. In Vue SPAs, avoid expecting SSR-like SEO without adding SSR or SSG. - **SEO expectations.** A pure SPA depends on client-side rendering, which new sites see indexed inconsistently. If organic traffic matters in month one, use Nuxt with SSR or static generation for public pages. To keep content flowing, consider an external helper like RankGoat for posting blogs, earning dofollow links, and fixing indexing issues. - **Auth on the server.**Do not trust client-only checks. Validate sessions in server routes and return 401 on data APIs. ``` ``` - **Payments and webhooks.** Subscription state lives on the server. Process webhooks on a server route, verify signatures, and update your database. In Nuxt, place this in *server/api/webhooks/payment.post.ts*. For Vue SPAs, use serverless functions or a small Node service. - **Internationalization sprawl.** Decide URL strategy early, such as */en* and */fr*. Centralize messages and naming, and set a default locale and fallback to avoid 404s on missing translations. - **Analytics duplication.** With SSR, ensure analytics runs only in the browser and only once. In Nuxt, put it in *plugins/analytics.client.ts* and avoid triggering it during SSR navigation. - **Cold starts and server limits.** On serverless, heavy SSR routes can suffer cold starts. Pre-render static pages and reserve SSR for pages that need user-specific data. - **File uploads.** Never upload directly to your app server in production. Use signed URLs for S3-compatible storage and store only object keys in your database. ## Key takeaways - Use Vue for small SPAs and widgets. Use Nuxt when you need SEO, speed, and a full-stack foundation. - Decide rendering per route. Pre-render marketing pages and keep dashboards client-first. - Timebox a proof in both stacks. The faster path to a protected, paid slice wins. - A Nuxt SaaS starter kit removes weeks of auth, payments, i18n, emails, content, and SEO setup. - Avoid common pitfalls by guarding browser-only code, handling auth on the server, and pre-rendering public pages. ## FAQ ### When should I choose Nuxt over Vue? Choose Nuxt when you need SEO-friendly public pages, faster first load, built-in routing and server APIs, or a clear structure for a growing SaaS. ### Can I start with Vue and switch to Nuxt later? Yes, but expect a refactor. Routing, meta handling, and data fetching patterns differ. If SEO or SSR is likely, start with Nuxt. ### Is a Nuxt SaaS starter kit worth it for a first launch? If you need auth, payments, i18n, emails, analytics, and a blog, a good starter kit can save weeks and reduce integration bugs. ### How do I make a Vue SPA SEO-friendly? Add an SSR layer or pre-render static pages. Without server rendering, search bots may index slower or miss content loaded after hydration. ### How do I handle payments in Nuxt? Use a supported payment provider for checkout and process webhooks in Nuxt server routes to update subscription status securely. # Nuxt Vue Guide: Step-by-Step to Build and Ship a SaaS App ![A practical Nuxt Vue guide with steps for auth, payments, i18n, SEO, and deployment, plus pitfalls to avoid so you can ship fast with a solid foundation.](https://shipahe.ad/images/blog/nuxt-vue-guide-step-by-step-to-build-and-ship-a-saas-app/post-737.webp){style="max-width:100%;border-radius:12px"} You searched for Nuxt Vue because you want a clear path from idea to working app. This guide gives you exact steps, concrete decisions to make, and checks that prevent rework. It reflects what consistently works to ship the first version fast without painting yourself into a corner. ## Choose your start: clean Nuxt or a Nuxt SaaS starter kit You have two good paths. Start from a clean Nuxt project and wire up everything yourself. Or use a Nuxt boilerplate built for SaaS so you start with authentication, payments, i18n, and admin already working. If time-to-first-customer matters, a Nuxt SaaS starter kit saves weeks of glue work and testing. If you plan to buy a Nuxt boilerplate, check for: - Protected routes via route middleware and server-side authorization, not client-only checks. - Payments for one-time and subscriptions with verified webhooks and an account billing UI. - Typed ORM with migrations and a seed strategy that never pollutes production. - S3-compatible uploads with presigned URLs, CORS examples, and signed downloads. - i18n with a visible language switch, locale-aware routes, and SEO-friendly hreflang. - Admin area with role-based access, audit logs, and a way to impersonate only with explicit approval. - SEO defaults, Open Graph images, a sitemap endpoint, and simple analytics. - Deployment scripts that run migrations and seed only what is safe in each env. When people say Nuxt SaaS boilerplate or Nuxt SaaS template, they want a repo with user accounts, checkout, and a dashboard that compiles on day one. The best ones also cover analytics, SEO basics, and file storage so you do not get stuck stitching services. Below, each step notes what you build from scratch versus what a starter kit usually provides out of the box. ## Build the core: from create to first deploy 1. **Create your project.** From scratch, run `npx nuxi init myapp`, then enable TypeScript strict, ESLint, and tests. With a starter kit, clone and run its setup script. Good kits ship a typed codebase with a preconfigured database and ORM plus migrations, so your models and APIs stay consistent as you scale. 2. **Set environment variables early.** Add `.env` and `.env.example`. Use `runtimeConfig` in `nuxt.config.ts` for server secrets, and `NUXT_PUBLIC_*` for safe client values. Define keys for database URLs, storage, OAuth, and payments. Set production values in your host before first deploy to avoid broken callbacks and failed webhooks. 3. **Authentication and protected pages.** Implement email-password, magic links, and Google sign-in if you need it. Keep sessions in httpOnly cookies with `SameSite=Lax` or `Strict` and short-lived tokens. Protect routes with `middleware/auth.global.ts` and enforce roles again on the server. A solid starter includes sign up, login, password reset, transactional emails, and examples for `/api/auth/callback` routing. 4. **Payments and checkout.** Support one-time purchases and subscriptions. Build a simple flow: pricing page to checkout session, return URL to a success page, and a billing portal link. Verify webhooks in `server/api/webhooks/payments.post.ts`, log event IDs, and make handling idempotent. Surface plan, renewal date, and failed payment status in the account page with a clear retry path. Many kits ship these flows and let you switch providers without rewriting UI. 5. **Database, ORM, and migrations.** Use Postgres with Prisma or Drizzle. Write idempotent migrations and run them on every deploy. Add composite indexes for frequent filters, use UUIDs, and avoid destructive ALTERs without a copy-then-swap plan. Seed only development data locally. A preconfigured ORM in a typed codebase makes refactors safer. 6. **File storage.** For uploads, use S3-compatible storage. Generate short-lived presigned URLs server-side, prefer presigned POST for large files, and store only the object key, size, and content type in your DB. Set bucket CORS to allow your origin, enforce max size client and server, and validate `Content-MD5` when it matters. A starter that already handles secure uploads saves a lot of trial and error. 7. **AI features where they help.** Keep AI calls on the server behind `server/api/*` endpoints. Support streaming responses for chat where possible, add per-user rate limits, and cap spend per account. Expose model selection in settings if it is core to the experience. Kits that include AI chat and generation with switchable models let you test quickly while logging usage to control cost. 8. **i18n and an in-app language switch.** Set up internationalization before your first page goes live. Keep strings in translation files, add a header toggle, and pick a route strategy such as prefix except default. Add `hreflang` and canonical tags so search engines map locales correctly. Early i18n avoids rewrites and expands reach from day one. 9. **Admin area and moderation.** Create an `/admin` layout and guard it with both middleware and server checks. Define the minimum privileges for each role, log admin actions, and never blend admin-only APIs with public ones. If a kit includes an Admin Panel, focus on your policies, not scaffolding UI. 10. **SEO, analytics, and content.** Use sensible defaults with `useSeoMeta`, generate Open Graph images for shareable pages, and ship a sitemap endpoint so every new page is indexable. Track pageviews, signups, and key actions. If you add a blog with Nuxt Content, make it multilingual and wire it into your sitemap to keep publishing simple. 11. **Cron jobs and lifecycle emails.** Schedule daily reports, email reminders, and cleanup via your host’s scheduler or an external cron pinging `/api/cron/*`. Make jobs idempotent with a run key so retries do not duplicate work. Transactional emails should cover password resets, welcomes, billing events, and limits reached, using templates tested on mobile. 12. **Deploy and verify.** Use a repeatable build with CI. Run tests, build, then apply DB migrations as part of release. After going live, test sign up, login, protected routes, checkout, webhooks, and language switching in production. Turn on error reporting, set alerts for webhook failures, and watch logs for the first 24 hours. ## Common pitfalls and the fixes - **Mixing server-only code into client components.** Keep secrets and API keys in server routes or Nitro handlers. Use composables that detect client versus server to avoid SSR crashes. - **Broken OAuth callbacks.** Configure exact redirect URIs in your provider and your app. A single trailing slash mismatch blocks all logins. - **Unverified webhooks.** Always verify signatures from your payment provider. Log every event ID and ignore duplicates to keep invoices and subscriptions in sync. - **Public env mixups.** Client-side reads only work for `NUXT_PUBLIC_*`. Put everything else in `runtimeConfig` so it stays server-only. - **i18n routes fighting SEO.** Decide between subpaths or domains per language, and ensure canonical tags point to the correct locale version. - **S3 uploads failing in production.** Set correct CORS for your bucket, enforce content type, and generate short-lived signed URLs server-side. Test with large files and slow networks. - **Cron jobs double-running.** Use a single scheduler per environment or add a distributed lock so you do not send duplicate emails. - **Migrations that wipe data.** Back up before deploy. Write forwards and backwards-safe migrations. Never change a column type without a copy-then-swap plan. - **Analytics with holes.** Track signups, activations, key feature use, and cancellations, not just pageviews. Confirm events fire in private windows and with blockers. ## Build and sell an AI tool with Nuxt Vue The fastest route is to start with a Nuxt SaaS starter kit so you get authentication, protected pages, payments, and AI generation ready on day one. Scope a narrow first release, price a single plan, and instrument analytics to see where users drop off. If your tool processes media, make sure file uploads and storage are stable before you try to grow. For example, a product like SubtitlesFast needs reliable uploads, a simple checkout with a subscription option, and clear account limits exposed in the UI. Ship a specific landing page with real examples, add a blog post showing outcomes, and include a friction-light trial that still collects email so you can send a welcome sequence. Meter usage server-side, cap spend per user, and show remaining credits in the header. Keep your admin panel lean so you can issue refunds, handle chargebacks, and block abuse without touching the database. Iterate weekly and ship one improvement tied directly to an analytics drop-off or a support ticket. ## Key takeaways - Pick your start. A Nuxt boilerplate with SaaS features gets you to first users faster than wiring everything from scratch. - Handle the basics early. Auth, payments, storage, i18n, SEO, and analytics are easier before launch than after. - Protect production. Verify webhooks, lock cron jobs, back up before migrations, and keep secrets server-side. - Ship fast, then measure. Let data guide your next sprint, not guesses. ## FAQ ### What is the difference between Nuxt and Vue for this stack? Vue is the frontend framework. Nuxt adds server rendering, file-based routing, server APIs, and conventions that speed up building production apps with Vue. ### Should I use a Nuxt SaaS starter kit or start from scratch? If you need authentication, payments, admin, and i18n soon, a starter kit saves weeks. If your app is unusual or you want to choose every dependency, start clean and assemble only what you need. ### How do I add payments to a Nuxt app safely? Use a provider with one-time and subscription support, keep keys server-side, verify webhook signatures, and update subscription status from webhook events, not the client. ### How do I secure protected pages and APIs in Nuxt? Use route middleware for gated pages, store sessions server-side, and put secrets in server routes or Nitro handlers. Never expose private keys in the client bundle. ### How can I add i18n without hurting SEO? Use a language switch with separate URLs per locale, add hreflang and canonical tags, and keep translations in files for easy updates. # Open source Nuxt starter alternatives and when to buy ![Build, fork, or buy a Nuxt starter? See concrete trade-offs, real costs, and a simple decision map to ship a SaaS or AI app fast without weeks of glue work.](https://shipahe.ad/images/blog/open-source-nuxt-starter-alternatives-and-when-to-buy/post-464.webp){style="max-width:100%;border-radius:12px"} You want to ship a Nuxt app fast without vanishing into weeks of plumbing. You are comparing free starters, forks, and paid kits, and trying to see the real work each path hides. Here is a practical way to choose and avoid expensive rework. Even a small tool like Jigsaw Station feels simple until you add signups, paid tiers, and email, then every seam in the stack starts to matter. ## Alternative 1: Build your own Nuxt stack with modules **Strengths.** Full control and a clean mental model. You pick each piece and keep only what you need. Typical choices include: - Auth with a session or JWT strategy, OAuth providers, and magic links - Postgres or MySQL with Prisma, plus typed schema and migrations - File uploads to S3-compatible storage with signed URLs - Transactional email via a provider like Postmark or Resend - i18n with route-based locales and an in-app switcher - Analytics with a privacy-friendly tracker or self-hosted suite - SEO using useHead or a sitemap and OG image module - Background jobs via Nitro cron, a queue, or an external scheduler **Trade-offs.** You own the glue and the edge cases. Concrete pitfalls that catch teams: - **Auth on SSR.** OAuth callbacks, cookie flags, and CSRF handling differ between server routes and client navigation. Protecting server-rendered pages requires guards at both the route and API levels. - **Payments and webhooks.** Idempotency keys, proration, retries, and out-of-order webhook delivery are easy to miss. You need tests to prove subscription state cannot drift. - **Uploads and access control.** Signed URLs must expire and be scoped. Public buckets leak. Private buckets break if clock skew or region mismatches slip in. - **i18n and SEO.** Locale prefixes, canonical tags, and default language redirects must agree, or you get duplicate content and broken links. - **Edge deployments.** Some Node APIs are not available on edge runtimes. Know what runs where before you pick a host. - **Configuration drift.** ENV naming, secrets per environment, and a repeatable local setup script save hours later. Without them, onboarding slows to a crawl. Even seasoned developers underestimate the time to harden auth, nail webhook flows, and close file access holes. A two week plan turns into two months when you hit production-only bugs. ## Alternative 2: Fork an open source Nuxt SaaS template **Strengths.** You start close to done. Many templates include a layout, a landing page, and basic auth. Swap the branding and deploy. For hackathons, a demo for a client, or a class project, it is the fastest way to show a working app. **Trade-offs.** You inherit someone else’s decisions and backlog. Maintainers do not owe you fixes. Before you commit, verify in your own environment: - **Auth really protects data.** Try private pages without a session, test magic links and social providers, and reload SSR pages to catch hydration gaps. - **Payments complete and persist.** Run both one-time and subscription flows with test cards, kill the network mid-flow, then confirm state via the dashboard and your database. - **Admin is usable.** Can you search users, ban spam accounts, and undo mistakes with audit trails or soft deletes. - **Database is safe to evolve.** Typed models, repeatable migrations, and seed data reduce risk during refactors. - **Uploads and emails work end to end.** Confirm signed URLs, attachment sizes, and production SMTP settings with a real provider. - **CI, tests, and releases exist.** Look for a passing CI workflow, a recent release, and a changelog. A stale lockfile is a red flag. Most open source starters stop at demo-grade features. That is fine if your goal is to learn and extend, but budget time to harden everything before you ask users for money. ## Alternative 3: Buy a production-ready Nuxt SaaS starter kit **Strengths.** You trade a fee for a head start on the parts that usually slip. A good Nuxt SaaS boilerplate ships with guarded routes, end-to-end auth, an admin area, payments with webhooks and receipts, i18n, transactional emails, analytics, SEO, storage, and a documented deployment path. If your plan is to charge soon, this is often the shortest path to a stable baseline. Shipahe.ad offers a Nuxt starter kit built for production. It includes protected pages, authentication with email and password, magic links, and Google, an admin panel to view users and ban spammers, and checkout flows for one-time or subscription payments with multiple, swappable providers. You get multi-language support with an in-app language switch, transactional emails with pre-made templates, a prebuilt landing page you can customize by swapping text, a blog powered by Nuxt Content, built-in analytics for pageviews and signups, SEO automation for meta tags, Open Graph images, and sitemaps, a preconfigured database with an ORM and typed codebase, S3-compatible file uploads, scheduled cron jobs for reports and reminders, and AI features like chat, text, and image generation with switchable GPT models. It is also designed to work well with AI coding tools like Cursor and Claude. If you are asking How do i build and sell an ai tool online, a Nuxt SaaS starter kit like this gives you both generation features and payments on day one. **Trade-offs.** You adopt the kit’s conventions. That is the point, but it still means learning a codebase. If you want a different ORM or a custom auth stack, budget time to adapt the wiring. ## Cost, migration, and support **Time and money.** Free often costs more in hours. Conservative build times for production features in a Nuxt app: - Auth with protected routes, magic links, social sign-in: 16 to 40 hours - Payments with subscriptions, webhooks, retries, invoices: 24 to 60 hours - Transactional emails with templates and delivery: 10 to 16 hours - Multi-language UI with a language switch and routing: 8 to 20 hours - Admin area with user search, actions, and audits: 12 to 24 hours - Analytics setup and basic dashboards: 6 to 12 hours - SEO for meta, OG images, and sitemap: 6 to 10 hours - S3-compatible uploads with secure access: 12 to 24 hours - Scheduled jobs for emails and reports: 4 to 8 hours - AI chat and generation features: 16 to 40 hours At modest rates, 120 to 250 hours dwarfs the price of a paid Nuxt boilerplate. That does not include upgrades, bug fixes, or rewrites when dependencies change. **Migration path.** If you start with DIY or a forked template, isolate your domain logic so you can switch foundations later. Practical steps: - Wrap auth, payments, storage, and email in a service layer with typed interfaces so calls are easy to remap - Keep one ORM and a clean migration history so you can export and import data safely - Store secrets in a single config module, document required ENV, and script local setup - Use feature flags to replace modules in small steps, not a big bang cutover - Plan data mapping for users and subscriptions, including password hash formats and provider IDs - Run both stacks in parallel for a few days and replay webhooks to catch edge cases before flipping traffic **Support reality.** With DIY or open source, support is you and the community. With a paid kit, you get a cohesive stack, consistent patterns, and documentation that cuts onboarding time. If your roadmap moves weekly, fewer decisions add up to faster delivery. **Decision map.** - If you are learning Nuxt or exploring, build your own stack. - If you need an MVP this week, fork a template and budget time to harden it. - If you plan to charge within a month, buy a Nuxt starter and focus on product logic. - If your product is an AI tool with paid tiers, prefer a Nuxt kit that ships generation plus subscriptions on day one. - If compliance or uptime risk matters, pick the path that minimizes custom glue and unclear ownership. ## Key takeaways - Open source starters get you moving, but production features like auth, payments, i18n, admin, analytics, SEO, storage, cron, emails, and AI add up fast. - DIY gives control. Forked templates give speed. Paid Nuxt SaaS starter kits give a stable baseline and a shorter path to revenue. - Total cost of ownership often makes buying a Nuxt boilerplate cheaper within weeks, not months. - For AI products, built-in generation plus subscriptions answers How do i build and sell an ai tool online with fewer moving parts. # PaaS vs SaaS: Pick the Right Mix and Ship Your Nuxt App Fast ![Clear PaaS vs SaaS guidance for Nuxt builders, with a concrete stack, setup checklist, and pitfalls so you ship fast with auth, payments, i18n, and SEO.](https://shipahe.ad/images/blog/paas-vs-saas-choose-ship-nuxt-app-fast/post-727.webp){style="max-width:100%;border-radius:12px"} You can lose a week debating PaaS vs SaaS while your app sits. The way through is simple: decide what you must own, rent out the rest, and ship on a stack that will not box you in later. Below is a practical playbook for Nuxt teams. It explains PaaS vs SaaS in the context of a real Nuxt app, gives you a reference stack you can copy, and highlights the traps that slow launches. It reflects what actually works when your goal is to get to paid users fast without rewriting your stack in three months. ## What PaaS vs SaaS means for a Nuxt app Platform as a Service runs your code without you managing servers. You push your Nuxt app, the platform builds and serves it, handles TLS, routing, autoscaling, cron, logs, and often provides add-ons like managed databases and queues. Your application logic, server routes, and UI are yours. Software as a Service gives you a finished capability behind an API or UI. Typical uses are auth, payments, email delivery, file storage, analytics, error tracking, and search. You do not run it. You pay for usage and rely on their SLAs and security teams. Most Nuxt products do best with a mix. Put your differentiating code on a PaaS so you can move fast. Use SaaS for common building blocks you would rather not maintain. Shift that line if you have hard constraints like data residency, private networking, enterprise SSO, or strict latency budgets. ## Choose what to build vs buy - Define the core jobs. Write the 3 - 5 user jobs your product must nail. Keep that logic and the supporting data model in your codebase. Everything else is support work. - Note constraints early. List target regions, privacy rules, uptime needs, traffic shape, and team skills. If you handle PII, plan data residency. If you need private networking, check whether your PaaS supports private databases and VPC peering. - Pick your runtime shape. A Nuxt 3 starter keeps UI, server routes, and API calls together through Nitro. You get file-based routing, middleware, server/api endpoints for callbacks and webhooks, and SSR out of the box. A well-made Nuxt SaaS starter kit removes days of setup across auth, billing, admin, and SEO so you start with production rails instead of a blank page. - Decide where to buy. For a new product, buy a Nuxt boilerplate that already includes protected routes, email and Google auth, an admin area, subscriptions and one-time payments with webhooks, transactional emails, an ORM with typed migrations, S3-compatible storage, i18n with a language switcher, SEO utilities, a blog powered by Nuxt Content, cron jobs, and optional AI chat, text, and image generation modules. That checklist is boring to build and costly to get wrong. - Wire your workflows. Keep a .env.example with every required var. Use typed ORM migrations so schema changes are reviewable and safe. Seed local data so every developer can run the app in minutes. Add basic CI for type checks and linting. Ship with a staging environment and a simple smoke test that runs login, checkout, i18n toggle, and an admin action. - Launch in stages. Stand up staging on your PaaS. Run checkout with test cards. Verify email delivery and domain auth. Switch languages and confirm copy falls back correctly. Trigger webhooks and check signature verification. When it is clean, point the domain, turn on real payments, and enable analytics. ## A Nuxt SaaS reference stack and setup checklist Use this as a starting point and adjust for your needs. - Application: Nuxt 3 app using Nitro for server routes. Keep auth callbacks under /server/routes, webhooks under /server/routes/webhooks, and internal API under /server/api. Use route middleware to protect pages. Centralize feature flags and app config in runtimeConfig. - Hosting: Pick a PaaS with first-class Node support, build caching, zero-downtime deploys, cron or scheduled jobs, logs, environment variables, and rollbacks. Check websocket and server-sent events support if you stream AI responses. Understand limits like cold starts, request timeouts, and ephemeral disk. - Database: Managed PostgreSQL or MySQL. Use an ORM like Prisma or Drizzle with typed migrations. If your PaaS uses serverless functions, add a connection pooler or proxy. For zero-downtime changes, prefer additive migrations, backfill first, then swap columns. Back up before destructive changes. - Auth: Email/password, magic links, and a social login like Google cover most cases. Store sessions as httpOnly, secure cookies. Set SameSite=Lax, rotate session secrets, and expire sessions. Protect against CSRF on sensitive POST endpoints. Put role checks in server-side middleware. Keep an admin role separate from user roles and audit admin actions. - Payments: Support subscriptions and one-time credits. Map plans to immutable price IDs in code. Implement webhooks with signature verification and idempotency keys. Build a customer portal link so users can self-serve changes. Configure taxes and invoices before launch. Add usage limits in code to protect margins. - Storage: S3-compatible bucket with private ACL by default. Serve files via signed URLs that expire quickly. Set CORS for your app origins. For images, generate thumbnails in a worker so your app response stays fast. - Emails: Use a transactional provider. Authenticate your domain with SPF, DKIM, and DMARC. Keep templates versioned in your repo, not in a dashboard. Send on key events: welcomes, password reset, email verification, receipts, failed payment notices, and trial-expiry reminders. Handle bounces and complaints. - Analytics and SEO: Track signups, activations, key feature use, cancellations, and revenue-related events. Tag each event with plan and locale to spot friction. In Nuxt, set titles and meta with useHead. Generate a sitemap and robots.txt on build. Include Open Graph images for main pages and your blog. Consider a /changelog route for small updates. - Observability: Enable structured logs and save them for at least 14 days. Add uptime checks for app, API, and webhook endpoints. Alert on error rate spikes and failed checkouts. Capture unhandled rejections and log context like user ID and request ID. - Deployment: Lock Node and package versions. Cache node\_modules or use a PnP-aware installer to speed builds. Run nuxi build and a smoke test before promoting. Keep separate staging and production secrets. Prefer canary deploys for risky changes. Document a rollback. - Go-to-market workflow: Ship a basic landing page and pricing table on day one. Blog with Nuxt Content so you can publish from Markdown. If you repurpose social threads, X-Post-Copier lets you pull an X.com post with text, media, author, and links straight into your clipboard for a changelog entry or blog post. ## Pitfalls and portability tips - Reinventing auth. Login, reset flows, magic links, and session security take longer than you think. Use the boilerplate’s auth patterns and tests. - Hard-coding a single payment provider. Wrap your billing logic so you can swap later. Keep product and price IDs in config, not sprinkled in components. - Skipping i18n until later. Add a locale switch from day one, store the choice in a cookie, and keep copy in translation files so you can add languages without refactoring. - Forgetting domain auth for email. Verify SPF, DKIM, and DMARC in staging. Test password resets and receipts across providers like Gmail and Outlook. - Storing files on app disk. App instances are ephemeral. Use S3-compatible storage and signed URLs. Clean up orphaned files with a scheduled job. - Weak webhook handling. Verify signatures, use idempotency, and process in a background job to avoid timeouts. Log the raw payload securely. - No admin area. Support cannot help without visibility. Ship an admin view with user search, impersonation for debugging, spam controls, and audit logs. - Ignoring connection limits. Serverless functions can exhaust DB connections. Use pooling and keep-alive. Close clients in long-lived workers. - Over-coupling to PaaS extras. Prefer standard runtimes, env vars, and S3-compatible storage. Avoid proprietary API calls you cannot reproduce elsewhere. - Missing rate limits. Add per-user and per-IP limits on auth, file uploads, and AI endpoints. Return clear errors and surface limits in the UI. ## Ship an AI tool this week Pick one job. For example, take a folder of images and produce consistent product shots, or turn a meeting transcript into a clean summary. Wire the API to your model of choice behind a server route so you can swap models later without touching the client. Stream partial results with server-sent events for better UX and lower timeouts. Bill from day one. Offer a small credit pack for one-off use and a subscription with higher limits. Track usage in your database and stop jobs when limits are reached. Expose current usage on the billing page so customers know what to expect. Protect your margins. Add per-minute and per-user rate limits, queue long jobs, and retry with backoff on transient model errors. Log prompt inputs and token counts carefully and avoid storing sensitive user data unless you need it. Make it trustworthy. Require login for dashboards, send clear transactional emails, and show a simple audit trail of actions like uploads and generations. Watch your analytics for where users stall and fix those screens first. ## Key takeaways - Own the product-specific code on a PaaS. Rent common capabilities as SaaS so you can move faster. - A solid Nuxt starter kit shortens setup and gives you auth, payments, admin, i18n, SEO, storage, cron, analytics, and a blog on day one. - Keep portability with standard env vars, S3-compatible storage, typed migrations, and a billing layer that can swap providers. - Ship in stages with a staging app, test cards, verified email domain, webhook checks, and a smoke test you can run before every deploy. - For AI tools, start narrow, meter usage, price clearly, and stream results to improve UX and reduce failures. ## FAQ ### What is the main difference between PaaS and SaaS? PaaS runs your custom code and handles deploys, scaling, and infra. SaaS gives you a finished capability like payments or email through an API or UI. ### Which PaaS works best for a Nuxt app? Pick a PaaS that supports Node runtimes, environment variables, SSL, rollbacks, cron, and good logs. Most modern platforms that run Node will handle a Nuxt app well. ### When should I buy a Nuxt boilerplate instead of building from scratch? Buy when you need auth, payments, emails, admin, storage, analytics, SEO, and a landing page now. A starter saves weeks and reduces security and billing mistakes. ### Can I switch payment providers later? Yes, if your template separates billing logic from provider code. Choose a starter with swappable payment providers and keep webhook handling modular. ### How do I price an AI tool launched with Nuxt? Start with a low-friction monthly plan and an entry credit pack. Use analytics to see usage patterns, then tune tiers around outcomes users value. # SaaS Post-Launch Checklist – 7 Steps to a Secure Startup Clicking "deploy" is a massive milestone, but it's only the beginning. A "hardened" app is the difference between a project that survives going viral and one that crashes under the weight of its first 100 users. If you skip the post-launch audit, a simple configuration error could lead to a data breach or a broken billing flow on Day 1. This is the exact **SaaS launch checklist** I use to ensure my apps are secure, scalable, and actually ready for paying customers. --- ## Why "Hardening" Matters for Founders Most developers focus on features. Successful founders focus on infrastructure. Doing **post launch hardening** correctly helps you: - **Build User Trust:** People won't pay for an app that feels buggy or unsafe. - **Avoid Middle-of-the-Night Emergencies:** Proper monitoring saves you from waking up to a broken site. - **Scale Without Friction:** Being prepared means handling 1,000 users is as easy as handling 10. --- ## The 7-Step SaaS Launch Checklist ### 1. Audit Your Authentication Security isn't an afterthought. Ensure you are following **SaaS security best practices** by: - Enforcing strong password requirements. - Using a trusted auth provider like Better Auth. - Setting up Multi-Factor Authentication (MFA) for your own admin accounts. ### 2. Verify Your "Live" Speed Localhost is always fast, but the real world isn't. Run your live URL through PageSpeed Insights. If your mobile score is below 80, your SEO and conversion rates will suffer. ### 3. Automate Your Backups If your database disappeared tomorrow, would your business survive? **Secure your SaaS** by setting up daily, automated backups. Providers like Supabase or Turso do this with one click—make sure it is actually turned on. ### 4. Implement Error Tracking Don't wait for a user to email you a screenshot of a broken page. Use a tool like Sentry or GlitchTip. It will notify you the second a bug occurs so you can fix it before your next customer hits that same wall. ### 5. Check Your SEO Fundamentals Ensure your `robots.txt` isn't blocking Google. Verify that your sitemap is submitted to Google Search Console. A **SaaS infrastructure guide** isn't complete without making sure people can actually find your app. ### 6. The "Legal Minimum" You are dealing with user data and money. You must have: - **Terms of Service:** Protects your business. - **Privacy Policy:** Legally required (GDPR/CCPA) and builds trust. - **Cookie Consent:** Essential if you use tracking scripts. ### 7. Setup Analytics for Growth If you don't know where your users are coming from, you don't have a business. Install a privacy-first analytics tool (like Plausible or Umami) to see which pages are actually converting. --- ## Preparing Your SaaS for Scale Scaling isn't just about "bigger servers." It is about having a codebase that can be updated without breaking everything. If you started with [ShipAhead](https://shipahe.ad){rel=""nofollow""}, much of this hardening is already baked into the foundation. From secure auth to optimized page loads, we designed the boilerplate to be "launch-ready" from the first commit. --- ## Your Path Forward Don't let the excitement of launching distract you from the importance of stability. Spend 60 minutes today going through this **SaaS launch checklist**. A reliable app is a profitable app. If you haven't launched yet, get [ShipAhead](https://shipahe.ad){rel=""nofollow""} and start with a foundation that is already hardened and ready for world-class scale. # Scale SaaS with Nuxt: analytics, i18n, admin, emails, SEO ![Scale your Nuxt SaaS with analytics, i18n, admin, transactional emails, cron jobs, and SEO defaults so you grow users faster and cut operational toil.](https://shipahe.ad/images/blog/scale-saas-with-nuxt-analytics-i18n-admin-emails/post-754.webp){style="max-width:100%;border-radius:12px"} Scale does not come from adding one flashy feature. It comes from short feedback loops and reliable systems that keep working as your user count climbs. If you build on Nuxt, the fastest path is to wire analytics, localization, admin controls, lifecycle emails, automation, and SEO defaults on day one, then iterate every week. This playbook shows how a Nuxt SaaS starter kit with built-in analytics, multi-language support, an admin panel, transactional emails, cron jobs, SEO automation, authentication, payments, and file storage helps you ship faster and grow with less custom plumbing. ## Measure what matters with built-in analytics Most teams watch too many charts and miss the one pattern that predicts growth. Keep a compact metric set tied to time-to-value and habit-forming use. ### Pick a compact metric set - Acquisition: daily signups by channel and % that start onboarding within 24 hours. - Activation: users who hit a first value event within 7 days. Define a single event that signals value, such as report\_sent, project\_created, or file\_uploaded. - Engagement: weekly active users and the median actions per active user. - Conversion: free to paid within 30 days, or trial to paid if you run trials. - Retention: week 4 return rate and 90-day logo retention. Instrument three to five product events and make them consistent. Use a single helper to send events from the client and the server so you capture both UI and background actions. Store user\_id, event\_name, route, and a small JSON payload for context. Keep event names stable so you can compare cohorts over time. ### Instrument before you polish Add tracking the moment a feature is clickable. Capture the time from account creation to first value event, and the percent of users who reach that event in their first session. If many users stall between step two and three of onboarding, collapse steps or prefill data. If they trigger the value event but do not repeat it, surface a second obvious use case on the dashboard. ### Turn numbers into decisions Set a weekly analytics cadence. Review signups, activation, and value events every Monday with the team. Pick one bet for the week that should move one metric. Examples: reorder onboarding to put file upload first, pre-create a sample project on signup, or shorten a form. Because the kit’s analytics are already wired, you see the impact in days, not weeks. ## Localize fast with an in-app i18n switch International users will try your product before you feel ready. If your UI speaks only one language, many will churn in the first minute. An in-app language switch and clean locale files let you test real demand without a rewrite. ### Choose locales with data and scope tightly Pick one or two non-English locales based on traffic, waitlist signups, or early customer interviews. Translate only the pages that drive activation: landing page, signup, onboarding, and the main dashboard actions. Leave deep settings and long help text for later. ### Centralize copy and format correctly Keep all user-facing text in locale files, not in components. Use short sentences and string interpolation that avoids grammar traps. Standardize number, date, and currency formatting by locale so totals, plan prices, and timestamps feel native. Add a fallback locale to catch missing keys during deploys. ### Ship the switch, then watch behavior Release the language toggle early. Announce it in your changelog and a short email. Segment analytics by locale and compare activation and retention. If one market outperforms, add translated onboarding videos and a local pricing page. Your vue and Nuxt starter kit should make this a config change, not a refactor. ## Operate with an admin and scheduled automation Traffic without control invites spam, fraud, and slow support. An admin panel plus simple scheduled jobs turns chaos into a short daily checklist. ### Daily moderation checklist - Review new accounts from the last 24 hours. Ban obvious spam and free up taken usernames. - Scan high-usage accounts. Confirm they are real businesses, not scripts hitting an endpoint. - Check error spikes and slow queries from the last day. If one tenant is the cause, rate-limit fairly. - Skim queued support tickets. Use admin context to answer with one clear next step. Good admin screens include search by email or domain, last login, recent events, plan, invoices, flags, and notes. Role-based access keeps sensitive actions behind admin-only routes. Log every admin action with who, what, and when. Enable 2FA for admin users to reduce risk. ### Resolve issues fast with context When a user writes in, open their admin profile while your analytics are visible. You should see last login, last error, recent value events, and current plan. Example actions: resend email verification, reset a stuck onboarding step, or credit an invoice. Clear, specific fixes build trust faster than any ad spend. ### Automate lifecycle emails with cron Churn often begins with silence. Transactional emails and small scheduled jobs fill the gap by nudging users when they stall and celebrating progress when they act. ### Map a simple email ladder - Welcome on signup. Set one expectation and one action. - Activation nudge at 48 hours if no value event. Short how-to plus a link to that exact screen. - Usage confirmation right after a value event. Reinforce benefit and show the next action. - Weekly summary if inactive. One CTA to return. If they are active, send a usage digest they can share. Use cron jobs to schedule checks and sends. Examples: run a daily job at 09:00 to find users who signed up yesterday and did not complete onboarding, then send a short nudge. Run a weekly job on Monday to email power users a usage summary for their team. Make jobs idempotent by storing last\_run\_at and message\_id so you never double send. Respect deliverability with clear subjects, a recognizable from name, and working unsubscribe for non-transactional mail. Set SPF, DKIM, and DMARC before you scale volume. This pattern applies across products. A service like ApplyTOP needs timely job alerts and progress updates so seekers do not miss an opportunity. Your app is the same. If an action matters, schedule the check and send the message. ### Weekly operating rhythm - Monday: review signups, activation, value events, and top support themes. Pick one bet. - Tuesday to Thursday: ship the change, update locale files if needed, verify admin flows, and watch leading indicators. - Friday: adjust cron jobs and transactional emails to support the change. Publish a short changelog or blog note. ## SEO defaults that compound SEO feels slow until compounding kicks in. Set smart defaults so you never skip basics during a busy release, then publish on a cadence. ### Site structure and technical basics - Group by intent. Landing pages for use cases and plans, docs for how-to depth, and a blog for education and updates. - Clean URLs, unique titles, and specific meta descriptions. Automate Open Graph and Twitter images per page so shares look good. - Generate a sitemap and keep it fresh on deploy. Add canonical tags to prevent duplicates. - Keep pages fast. Optimize images, prefetch critical routes, and avoid blocking scripts. A fast app reduces bounce and lifts crawl rate. ### Publish helpful content on a schedule Use the built-in blog powered by Nuxt Content and ship in Markdown. Aim for one useful post per week that answers a real query. If you are asking yourself how to build and sell an AI tool online, document your own path. Share stack choices, costs, mistakes, and results. Posts that show real work attract readers who convert. ### Localize your top pages Translate your highest-converting landing pages and the top onboarding doc for your best non-English locale. Link translated pages from the main navigation and related posts so discovery is straightforward. As your sitemap updates on deploy, search engines pick up new locales quickly. Pair this with the in-app language switch so users move from search to activation without friction. When you run on a Nuxt SaaS starter kit that already includes analytics, an admin panel, i18n, transactional emails, cron jobs, SEO tools, auth, payments, S3-compatible uploads, and a prebuilt landing page, you skip months of plumbing and spend your time on the product. That is how you reach first revenue faster. ## Key takeaways - Track a small set of metrics tied to first value and repeat use, not vanity counts. - Ship the language switch early and focus translations on the flows that drive activation. - Use the admin panel daily to review new accounts, resolve issues with context, and block abuse fast. - Automate lifecycle nudges with transactional emails and cron jobs. Make jobs idempotent and predictable. - Rely on SEO defaults, clean structure, and a consistent blog cadence to compound growth. ## FAQ ### How can built-in analytics help me scale a Nuxt SaaS? They track pageviews, signups, and key user behavior so you can measure activation, feature use, and retention without wiring a separate analytics stack. ### What should I localize first when adding i18n? Translate the landing page, signup, onboarding, and core dashboard actions. Add more pages after you see traction in a new locale. ### Which lifecycle emails move the needle most? A clear welcome, a 48-hour activation nudge, a confirmation after a value event, and a weekly reminder for inactive users are reliable starters. ### Do I need a custom admin to manage growth? Not at first. A built-in admin that shows users, lets you manage accounts, and ban spammers is enough to keep operations under control. ### What should I look for in a Nuxt SaaS starter kit? Analytics, i18n, admin, transactional emails, cron jobs, SEO tools, authentication, payments, and S3-compatible file storage in a typed codebase. # Ship fast with Nuxt: 5 steps to launch a SaaS in one week ![Launch a paid Nuxt app in a week with a SaaS starter kit. 5 focused steps cover auth, payments, i18n, SEO, emails, analytics, cron jobs, and deployment.](https://shipahe.ad/images/blog/ship-fast-with-nuxt-7-steps-to-launch-a-saas-in-one-week/post-815.webp){style="max-width:100%;border-radius:12px"} Seven days is enough to launch something people can pay for if you cut scope to the minimum and refuse to build plumbing. A solid Nuxt starter kit gives you auth, payments, i18n, SEO defaults, admin, analytics, and cron jobs so you spend your time proving value, not wiring. This is the exact path we use when we turn ideas into revenue. Keep the target tight, ship daily, and make the paid path obvious. ## 1. Define the smallest sellable slice Pick one audience, one job, and one paid action. Examples: - AI: generate 5 product descriptions and export to CSV - Marketing: track top 10 SERP changes for a keyword and email a weekly diff - Dev: convert a JSON schema to TypeScript types and share a link Write a one-week schedule with daily outcomes, not tasks: - Day 1: scope the paid action, write homepage copy, define success metric - Day 2: ship landing page + signup - Day 3: price, checkout, and a protected thank-you state - Day 4: working demo of the core feature behind auth - Day 5: i18n essentials + SEO defaults - Day 6: production deploy, webhooks, scheduled job - Day 7: announce, measure, iterate Success is binary: a stranger can land, sign up, pay, and use a protected feature in under five minutes. If you prefer to buy instead of wire from scratch, pick a Nuxt/Vue SaaS boilerplate with authentication, payments, protected routes, admin, analytics, email, and cron jobs already in place. The Nuxt/Vue boilerplate from shipahe.ad is designed for this and it works well with AI coding tools like Cursor and Claude so you type less and move faster. ## 2. Ship the surface: landing page and copy Use the prebuilt landing page so you get to credible fast. Replace lorem ipsum with a clear promise: - Headline: outcome in plain English. Format: Do X so you can Y. Example: Generate product copy that matches your brand in 30 seconds. - Subhead: who it is for. Example: For solo sellers and small shops that need listings fast. - Primary CTA: a specific action. Example: Start free trial, Generate a sample, Buy now. Add one screenshot or short clip that proves the promise. If you sell an output, show a sample result. If you sell a workflow, show the key step. Keep the nav minimal so users go straight to signup or checkout. Wire basic events so you can read behavior on Day 1. Track `cta_clicked`, `signup_started`, `checkout_started`, and `purchase_completed`. Your starter kit’s analytics integration should expose a simple `track()` helper you can call from button clicks. Use structured copy, not feature lists. Explain how the paid action works, what the user gets after paying, and what happens next. If you have an FAQ, keep it short and push anything complex to support after launch. ## 3. Lock the path to value: auth, protected routes, pricing, checkout Turn on authentication so users can create an account and come back. Offer email + password for reliability, magic links for low friction, and Google sign-in for speed. Add password reset and a short welcome email using the transactional templates included in your kit. Create a protected page that contains the value. Examples: `/generate`, `/export`, `/dashboard`. Gate it with route middleware so anonymous users are redirected to signup and then back to their original destination. In Nuxt this is a small `defineNuxtRouteMiddleware` that checks session state. Decide how you earn the first dollar. Keep it simple: - One-time purchase if the value is a single export or download - Monthly subscription if the value repeats, like weekly reports or usage credits Start with one plan. You can add tiers after you see usage patterns. Use the built-in checkout flow from your kit so you avoid PCI scope. Stripe Checkout, Lemon Squeezy, or Paddle are fine. Add success and cancel routes, then test the full loop: create a new user, pay with a test card, land on a protected thank-you page, and see your entitlement flip in the session without refresh. Process webhooks to keep billing state correct. Your kit should include a secure webhook endpoint like `/api/webhooks/payments`. Verify signatures, map the event to the user account, record `subscription_active`, and handle cancellations. Use idempotency to avoid double-processing. Send a post-purchase confirmation from your transactional email provider (Resend, Postmark, or SendGrid work well). Keep it short: what they bought, how to access it, and where to get help. Let the payment provider send the receipt. Use the admin panel on Day 3. You should be able to search users, view subscriptions, and ban obvious spam. If roles exist, keep it simple: `user`, `admin`. Protect admin routes with role checks in middleware. ## 4. Localize essentials and set SEO defaults Internationalization helps discovery and trust, but you only need the basics to launch. Turn on the language switcher and translate the minimum set: homepage headline, subhead, CTA, primary buttons, and key error messages. Add locales to your i18n config and store phrases in JSON. You can expand content later without touching layout. Set SEO defaults once so every page has sensible metadata: - Global title template in `app.config.ts` so pages render as `Page Title | Product` - Per-page `useSeoMeta()` for title, description, canonical URL - Open Graph and Twitter images with a default fallback so link previews always look right - Robots and sitemap enabled so search engines can crawl new pages without extra work If your kit includes a blog via Nuxt Content, wire it but do not block on publishing long-form posts this week. A single “How it works” page or a short “What’s new” note is enough for launch. Focus the copy on the outcome, the paid action, and what happens after purchase. ## 5. Deploy, verify, announce, iterate Push production early so you can test with real domains, cookies, and third-party callbacks. Nuxt 3 runs on Nitro, so deployment to Vercel, Netlify, Render, or Fly is straightforward. Set environment variables for auth secrets, payment keys, webhook secrets, email provider keys, and any AI model keys if you use one. Confirm your custom domain and SSL before you share the link. Run a full checklist on devices you own and one you borrow: - Sign up with email + password, magic link, and Google - Reset a password and verify the email arrives and the link works - Start checkout, cancel, return to app, then complete checkout - Hit the protected page as a paid user and confirm entitlements - Trigger and receive the post-purchase email - View the user and payment state in the admin panel Add one scheduled job. Keep it useful and visible. Examples: daily usage summary to paid users, trial expiring reminder, or a weekly digest. Implement it as a server route like `/api/cron/daily` that calls your service layer. Use your host’s scheduler or an external cron service to hit it on schedule. Log start, success, and duration so you can spot failures fast. Announce with a tight message and a single screenshot. Post to your social accounts, niche communities you already participate in, and any email list you have. The goal is feedback and a few first customers, not a viral spike. Measure what happens with the built-in analytics. Look at pageviews, signups, checkout starts, and purchases. If the landing gets views but no signups, tighten the headline and move the CTA higher. If signups stall at checkout, show the value again on the checkout page and restate what happens after purchase. If buyers do not use the feature, add a short, in-app checklist and a day-1 nudge email. Building an AI tool? The playbook is the same with one twist: ship a working action behind auth on Day 4. Use the starter’s AI chat, text, or image components and switch the model to fit your use case. Gate the action behind a simple plan, count usage server-side, and send a day-1 tutorial email with a copyable prompt that gets a good result. ### Key takeaways - Define one paid action and build only what supports it. - Use the prebuilt landing, track core events, and keep navigation lean. - Enable auth, protect the value route, wire one simple plan, and test webhooks. - Translate the essentials and set global SEO defaults once. - Deploy early, verify the full flow in production, announce, and iterate the same day. ## FAQ ### Can I really launch a SaaS in one week with a Nuxt starter kit? Yes, if you cut scope to one sellable action and use a Nuxt SaaS boilerplate that already includes auth, payments, emails, SEO, analytics, and cron jobs. ### Do I need to build authentication from scratch? No. Use built-in email and password, magic links, and Google login, plus password reset and protected pages, so you focus on your core feature. ### How do I charge users on day one? Start with a single plan and connect the prebuilt checkout flow. Route users to a protected page after purchase and send a short confirmation email. ### How do I add AI features to my Nuxt app quickly? Use the ready-made AI chat, text generation, or image generation components, and switch GPT models to fit your use case. ### What if I need multiple languages at launch? Turn on the in-app language switch and translate only the essentials like the headline, CTA, and key labels. Expand coverage after you ship. # Stripe SaaS: A Step-by-Step Guide for Nuxt Builders ![Build a Stripe SaaS with a Nuxt starter kit: auth, checkout, subscriptions, webhooks, and billing UX. Step-by-step guide to ship fast with confidence.](https://shipahe.ad/images/blog/stripe-saas-step-by-step-guide-nuxt-builders/post-736.webp){style="max-width:100%;border-radius:12px"} You have a working idea and a Nuxt app taking shape, but recurring payments, access control, and onboarding keep slipping the launch date. This is the practical Stripe + Nuxt path I use to get a paid product live without gluing together half a dozen billing widgets. The same flow works whether you sell an AI feature set, a dashboard, or a narrow workflow tool. Stripe handles money and invoices. Your Nuxt app handles identity, entitlements, and UI. A good Nuxt SaaS boilerplate (like the one we ship at shipahe.ad) removes the busywork so you can focus on where your product is unique. ## What we’re building A production Stripe SaaS on top of a Vue/Nuxt starter kit that ships the unglamorous, critical pieces: - **Authentication** with protected routes. - **Checkout** for one-time and recurring plans. - **Webhooks** as the source of truth for billing state. - **Entitlements** that gate features, seats, and limits. - **Billing UX** with a clear account page, receipts, and self-serve changes. - **Localization + SEO** so your pricing and emails work in more than one market. - **Admin + analytics** to operate after launch, not just demo. If you buy a Nuxt boilerplate, you also get a prebuilt landing page, typed ORM models, cron scaffolds, and S3-compatible storage, all wired to run locally and deploy with one command. That is weeks saved. ## Implement Stripe in Nuxt: the essential wiring Stripe gives you reliable payments. Your job is to line up three flows: create checkout, confirm via webhook, and gate features in the app. Here is the concrete version. ### 1) Configure environment keys ``` ``` Keep provider keys in environment variables and load them via runtime config. Store the public price IDs for your plans so the client can start a session without exposing secrets. ### 2) Create Products and Prices In Stripe Dashboard (test mode), create one Product per plan and add monthly and annual Prices. If you need add-ons, create one-time Prices. Copy the price IDs into your .env. Name objects clearly: “Pro Monthly” and “Pro Annual” are easier to audit than “Plan A.” ### 3) Start a Checkout Session Expose a server endpoint that takes a price ID and returns a Stripe Checkout Session URL. Keep it server-side so you can attach the authenticated user. ``` ``` On the client, call this endpoint and redirect the browser to `session.url`. Do not update your database here beyond a temporary intent; the webhook is authoritative. ### 4) Verify webhooks and upsert subscriptions Webhooks are where your app learns the truth: a checkout completed, an invoice paid or failed, a subscription canceled or renewed. ``` ``` Store fields you will actually use in guards and UI: provider, customer ID, subscription ID, price ID, status, current period end, and plan attributes derived from the price. ### 5) Model plans as entitlements Plans change. Entitlements are stable. Keep a small map that turns a price ID into abilities and limits. This makes price experiments low risk. ``` ``` On login or webhook update, attach the current plan flags to the user’s session or fetch them server-side when rendering protected pages. ### 6) Gate features in route middleware and components ``` ``` Prefer server checks for write actions. For example, validate usage limits in API handlers so users cannot bypass the UI. If you are shipping an AI product, tie token spend or requests per minute to the same entitlements map. Log prompt/response counts per user and block when limits are hit. No separate stack required. ## Build the billing and operations layer Users expect to self-serve. Keep the Billing page boring and accurate: - Show plan name, renewal date, status, and payment method. - Link to Stripe’s Customer Portal for card updates, address, and invoice downloads. - Offer one-click upgrade paths that create a fresh checkout session. ``` ``` Emails matter more than most founders think. Send: - Welcome and receipt after first payment. - Trial ending 3 days and 1 day before expiry. - Payment failed, then dunning retries with a clear call to update the card. Automate the chores. Use cron-compatible jobs for: - Daily MRR and failed-payment summaries to your inbox or Slack. - Trial-to-paid conversion report. - Usage reset jobs for monthly limits. Your boilerplate’s admin panel should let you search by email, view subscription history, comp a month, or ban obvious spammers. Add a manual “set plan” action for support, but keep the webhook as the source of truth to prevent drift. Localization is not optional if your audience is global. Start with one extra language. Translate pricing copy, plan names, and the five transactional emails above. Ensure each locale has proper meta tags and a sitemap entry so search engines index the right pages. ## Launch and grow without guesswork Ship with a real landing page, not a placeholder. Put your top three outcomes above the fold, a short demo GIF, and a clear pricing grid that mirrors your actual entitlements. Turn on analytics on day one. Track: visits, signups, checkout starts, checkout completes, upgrade/downgrade events, and churn reasons. A simple funnel shows where to fix copy versus code. Post updates where your audience already hangs out. If you work in public on X, a [tweet copier Chrome extension](https://x-post-copier.online){rel=""dofollow""} helps turn scattered posts and screenshots into a weekly changelog or a clean case study. It saves time you should spend on product, not copy-paste. ## Common pitfalls - **Treating redirects as proof.** Users close tabs. Network calls drop. Only webhooks determine who paid and what they get. - **Binding logic to pricing.** Put entitlements in code or config, not in Stripe object names. Prices can change without breaking access checks. - **Burying provider specifics in your app.** Wrap Stripe behind a small PaymentProvider interface. You will thank yourself when you add a second processor or a regional method. - **Skipping test paths.** In test mode, run: trial start, upgrade, downgrade, cancel, card update, and payment failure. Keep logs. Fix every 400/500 until green. - **Forgetting localization and SPF/DKIM.** Translate subject lines and verify your sender domain so invoices do not land in spam. ## Key takeaways - Stripe handles money. Your Nuxt app owns identity, entitlements, and UI gates. - Model plans as flags tied to price IDs, and let webhooks be your billing source of truth. - Build a plain Billing page with self-serve portal links and clear emails. - Automate reports and limits so operations do not depend on your memory. - Launch with analytics and a real page. Use simple tools to repurpose social proof fast. ## FAQ ### Do I need Stripe Billing for a Nuxt SaaS, or is Checkout enough? Hosted Checkout covers most subscriptions. Add the hosted customer portal if you want self-serve plan changes and payment method updates without building custom UI. ### How should I test webhooks during development? Use your provider’s CLI or a tunneling tool to forward webhooks to your local server. Log every event and verify your signing secret in test mode first. ### What subscription data should I store in my database? Keep provider, customer ID, subscription ID, plan or price ID, status, current period end, and currency. Derive access from these fields and your plan flags. ### Can I switch payment providers later? Yes. If your starter kit supports multiple, swappable providers, keep a PaymentProvider interface and map shared events so you can migrate with minimal code changes. ### How do I tie AI features to paid plans? Add plan flags like ai\_chat or generation\_limits. Check these flags in middleware and rate-limit generation endpoints based on the active subscription. ## Recommended resources - [tweet copier Chrome extension](https://x-post-copier.online) # Stripe subscriptions in Nuxt: pricing, checkout, and webhooks ![Set up Stripe subscriptions in Nuxt 3 the right way: pricing, Checkout, webhooks, trials, taxes, emails, portal, and admin so you can launch fast.](https://shipahe.ad/images/blog/stripe-subscriptions-in-nuxt-pricing-checkout-and-webhooks/post-821.webp){style="max-width:100%;border-radius:12px"} Subscriptions bring predictable revenue, but wiring them into a Nuxt app goes wrong in small ways that cost you time and churn. The biggest mistakes we see: trusting a success URL, mixing test and live IDs, and letting the client choose any price. Here is a working baseline for Stripe subscriptions in Nuxt 3, with the practical decisions we ship in our Nuxt SaaS starter so you can move fast and still sleep at night. ## 1) Plan pricing tiers and trials Design the model before you code. Your pricing rules drive navigation, access control, and analytics. Write them down so the app, Stripe, and support scripts all match. - **Map features to tiers.** Decide what Free, Starter, and Pro actually unlock. Every paid feature should live behind protected routes and server-side checks. A simple pattern: public marketing pages, an authenticated area for Free, and a premium area visible only when a subscription is active. - **Intervals and amounts.** Lead with monthly. Offer annual with a clear percentage discount, not a vague “save big.” Keep names human: Starter $12/month, Team $29/month. Avoid more than three tiers at launch. - **Trials.** Choose length (7 or 14 days are common), whether a card is required, and enforce one trial per account. If abuse is a risk, limit trials to verified email domains or one per payment method. - **Seats vs usage.** For per-seat pricing, you will pass a *quantity* to Checkout and keep a seat count in your database. For usage, plan on metered billing and a daily job that reports usage to Stripe. - **International copy and currency.** If you localize, write pricing copy in your translation files now. Use `Intl.NumberFormat` for currency display and show the currency you actually bill in. Using a Nuxt SaaS starter kit means you can plug your tiers into a prebuilt pricing page, wire the calls to action once, and keep the offer consistent across the site and app. ## 2) Create products and prices in Stripe Stripe uses Products and Prices. One Product per tier, multiple Prices for intervals or currencies. 1. **Create products.** Add a Product for each tier. Match names and descriptions to what users see in-app. Use clear internal metadata like `plan_key` so support can search quickly. 2. **Add recurring prices.** For each Product, create Prices for monthly and annual with the right currency and amount. If you offer trials, set *trial\_period\_days* on the Price or pass it in Checkout when you create the session. 3. **Use lookup keys.** Set a `lookup_key` like `starter_monthly` instead of hardcoding Price IDs in code. You can then reference prices by lookup key in different environments safely. 4. **Taxes and addresses.** If you collect tax, enable Stripe Tax or configure manual tax rates. Require billing address and VAT/tax IDs in Checkout when needed. 5. **Stay in test mode.** Do all setup in test first. Keep a checklist of Price IDs or lookup keys to avoid mixing with live later. In your app, keep a *plans* table that maps a `plan_key` to human labels and Stripe IDs. Suggested fields: `plan_key`, `stripe_product_id`, `stripe_price_id_monthly`, `stripe_price_id_annual`, `interval`, `features`, `active`. This lets you render pricing accurately and validate that any `priceId` coming from the client is actually one you sell. ## 3) Implement a subscription checkout in Nuxt Use a server route to create a Checkout Session. Never expose secret keys in the browser. Never grant access based on a success URL. ### Client flow - User clicks a plan button. The client calls `POST /api/billing/checkout` with a safe payload: `plan_key` (or a known `lookup_key`), optional `quantity`, and the current organization or user ID. - The server validates the plan against your database, resolves to a Stripe Price (monthly or annual), and creates a Checkout Session in *subscription* mode. Return only the session URL. - Redirect to the session URL. Stripe handles SCA and 3D Secure. - Stripe sends users back to your `success_url` or `cancel_url`. Show a friendly state, but do not activate access here. Wait for the webhook. ### Server considerations - **Associate customers.** When creating the session, pass the authenticated email and a saved `customer` ID if you have one. Returning customers keep their payment method and invoices in one place. - **Metadata.** Include `user_id` or `org_id` and `plan_key` in `metadata` so webhook handlers can join events to your records without extra queries. - **Quantities and seats.** For seat-based plans, pass `quantity` to Checkout and store it on your subscription record. Update when admins add or remove seats. - **Billing Portal.** Enable the Stripe Billing Portal and add a button in your app’s billing page so customers can update cards, change plans, or cancel without support. - **Protect content.** Gate premium routes via server middleware and API guards. Hide UI affordances, but always enforce on the server too. - **Environment config.** Keep `STRIPE_SECRET_KEY` and `STRIPE_WEBHOOK_SECRET` in `runtimeConfig`. Separate test and live values by environment. A Nuxt SaaS starter kit like shipahe.ad includes subscription checkout for one-time and recurring payments, swappable providers behind a small interface, user authentication, and protected pages. You focus on plans and copy, not plumbing. ## 4) Handle webhooks for lifecycle events Webhooks are the source of truth for access. Create a secure endpoint, verify signatures against the raw request body, and make idempotent updates to your database. ### Events to handle - **checkout.session.completed**. Read the session, capture `customer` and `subscription`, and attach the Stripe customer ID to your user or organization. Set subscription status to *active* or *trialing* based on the object. - **customer.subscription.updated**. Track `status`, `current_period_end`, `cancel_at_period_end`, `trial_end`, `items.price.id`, and `quantity`. This powers upgrade/downgrade UI, trial banners, and renewal notices. - **invoice.payment\_succeeded**. Confirm continued access, increment MRR metrics, and optionally send a payment confirmation email with a link to invoices. - **invoice.payment\_failed**. Mark the account *past\_due*, show in-app notices, and email a short, actionable message with a link to update the card. Do not immediately revoke access if Stripe will retry. - **customer.subscription.deleted**. Move users to Free and remove premium capabilities. Preserve data but hide premium features. ### Verification, idempotency, and retries - **Verify signatures.** Use your webhook signing secret to verify requests with the raw payload. In Nuxt, read the raw body before JSON parsing for signature checks. - **Idempotent updates.** Store processed Stripe `event.id` values in a table. If Stripe retries, your handler should be safe to run again. - **Fast acks, background jobs.** Do small updates inline, queue heavy work (reports, large emails) to a worker, and return 2xx quickly so Stripe stops retrying. Keep a *subscriptions* table with fields like `stripe_customer_id`, `stripe_subscription_id`, `price_id`, `status`, `current_period_end`, `cancel_at_period_end`, `trial_end`, and `quantity`. If you support teams, scope subscriptions to an `org_id` instead of a user. For local testing, use the Stripe CLI to forward events to `localhost` and trigger scenarios. A typical flow: listen, run through Checkout in test mode, and confirm your webhook updates the subscription row exactly once. ## 5) Receipts, dunning, upgrades, and proration After the basics work, refine renewals, failed payments, and plan changes so customers always know what will happen next. - **Receipts.** Let Stripe email receipts automatically. If you also want in-app messages, send a transactional email on *invoice.payment\_succeeded* with invoice links and a clear subject. - **Dunning.** Start simple with Stripe’s retry schedule. On *invoice.payment\_failed*, show a banner and send a concise email with a secure link to your billing page or portal. Escalate tone only after the final failed attempt. - **Upgrades and proration.** Stripe prorates by default when upgrading mid-cycle. Before confirming a change, call the upcoming invoice endpoint to show the customer what they will pay now and what renewals look like. Reflect `current_period_end` in UI. - **Trials to paid.** Send onboarding during the trial (*trial\_will\_end*) and right after *checkout.session.completed*. The goal is clear “first value” before the first charge. - **Analytics.** Track `plan_selected`, `checkout_started`, `checkout_completed`, and `subscription_activated`. Look for drop-offs between pricing and Checkout, and between Checkout and activation. ### Common pitfalls and how to avoid them - **Trusting the success page.** Only webhooks should activate access. Success URLs are easy to spoof. - **Mismatched environments.** Test keys with live Price IDs will fail. Keep test and live IDs and webhook secrets cleanly separated. - **Letting the client pick any price.** Resolve a server-side plan to a known Stripe Price. Reject unknown or mismatched IDs. - **Missing access checks.** Hide links in the UI, but also enforce access in server middleware and API handlers. - **No admin tooling.** Give support a way to look up users by email, see subscription status, resend emails, and apply courtesy extensions. - **Skipping local webhook tests.** Use a tunneling or CLI tool to forward events to `localhost` and exercise success, failure, cancel, upgrade, and downgrade paths. ### Tie it together with a Nuxt SaaS starter kit If you are weighing a Vue/Nuxt starter versus going from scratch, a ready-made Nuxt SaaS kit saves days of glue work. The shipahe.ad kit ships with user auth and protected pages, subscription Checkout flows for one-time and recurring payments, transactional email templates, an admin panel, scheduled cron jobs, and built-in analytics. Drop in your plans and copy, wire Stripe keys, and you have a working paywall with clear webhooks and a billing page that customers can self-serve from. ### Key takeaways - Decide tiers, intervals, trials, and access rules first. Put paid features behind protected routes and server checks. - Create Products and recurring Prices in Stripe test mode, use lookup keys, and store mappings in your database. - Create Checkout Sessions from a server endpoint. Activate access from webhooks only, never from success URLs. - Handle core lifecycle events, verify signatures on raw bodies, and make idempotent updates to your subscription table. - Use the Billing Portal, transactional emails, and basic analytics to reduce churn and clarify charges. The same plumbing powers a SaaS, a web app, or an AI tool. With a solid Nuxt starter and disciplined webhook handling, you can launch fast and charge with confidence. ## FAQ ### How do I test Stripe webhooks locally in a Nuxt app? Run your Nuxt server and use a tunneling or CLI tool to forward Stripe events to your local webhook URL. Verify signatures and log each event to confirm your update logic. ### Should I mark the user active after checkout success or only on webhooks? Only on webhooks. The success page can be spoofed. Use events like checkout.session.completed and customer.subscription.updated to flip access in your database. ### How do I handle free trials in Stripe with Nuxt? Set a trial on the Price or pass a trial during Checkout Session creation. Store trial end dates from webhooks and show them in your billing UI so users know when they will be charged. ### Can I switch payment providers later without rewriting my Nuxt front end? Yes if your server abstracts checkout creation and billing operations. A starter kit that supports multiple, swappable providers helps you keep the client code stable. ### What’s the best way to protect premium pages in Nuxt? Use authentication and route middleware to check subscription status before rendering. Also lock down the server APIs behind those pages to prevent direct access. # Best Nuxt Starter Kits for SaaS Projects: A Founder's Perspective Let's be real: search for "Nuxt starter kit" and you'll find a dozen repos that look great on paper but turn into a maintenance nightmare the moment you want to add a custom feature. In 2026, the game has changed. We're not just looking for "code that works." We're looking for an architecture that stays out of the way, handles the "boring" stuff (auth, billing, SEO), and—crucially—plays nice with AI coding agents. I've tried almost every **nuxt ui starter kit** and **nuxt saas starter kit** on this list. Here is my take on which one you should actually use for your next project. --- ## Why Use a Nuxt Starter Kit? What are the **benefits of using a pre-built application scaffold**? For founders and developers, the advantages are clear: - **Launch in Days, Not Weeks:** Skip the setup of authentication, stripe integrations, and database schemas. - **Production-Ready Architecture:** Most modern kits use **Nuxt 4 starter kit** patterns, ensuring your app is future-proof. - **Cost-Effective:** While some kits are paid, they are far more **affordable Nuxt starter kits** than hiring a developer to build the same infrastructure. --- ## Comparison Table: Nuxt Starter Kit 2026 Options & Alternatives | Starter Kit | Best For | Tech Stack | Key Features | Price | | :-------------------------------------------------------------------------- | :---------------------------- | :----------------------------- | :-------------------------------------------------------- | :------ | | **ShipAhead** | **Solo Founders & AI Coding** | **Nuxt 4 + Drizzle + Nuxt UI** | **Optimized for AI coding agents, AI-ready architecture** | **$99** | | [supastarter](https://supastarter.dev){rel=""nofollow""} | Enterprise Teams | Nuxt 4 + Prisma | Multi-tenancy, RBAC, I18n | $349+ | | [Nuxt Beyond](https://nuxtbeyond.com/){rel=""nofollow""} | Full-stack Web Apps | Nuxt 4 + Prisma | Robust boilerplate, good documentation | $59+ | | [Nuxt SaaS Kit](https://nuxtsaas.com){rel=""nofollow""} | Content-heavy SaaS | Nuxt 3 + Prisma | Blog module, Auth, Payments | $149 | | [SuperSaaS](https://supersaas.dev){rel=""nofollow""} | Custom Backend Logic | Vue 3 + Node | Modular components, Stripe | $149 | | [Nuxt Starter Kit](https://nuxtstarterkit.com/){rel=""nofollow""} | Minimal | Nuxt + Tailwind | Authentication, Simple DB | $99 | --- ## In-Depth Review: The Best Options for 2026 ### 1. ShipAhead (Top Pick for Nuxt 4) **ShipAhead** is currently the **best Nuxt starter kit optimized for AI coding agents**. It is built explicitly for the Nuxt 4 era and focuses on a clean architecture that AI coding assistants like Cursor and Copilot can understand instantly. - **Pros:** Full Nuxt 4 support, Drizzle ORM (fastest), pre-built SEO modules, AI-native structure. - **Best For:** Developers who want to build high-quality apps with AI assistance. - **Nuxt JS Starter Kit** perfection: Uses the latest standards. ### 2. supastarter for Nuxt One of the most mature options on the market. If you need a **nuxt saas starter kit** that handles complex team management and multi-tenancy out of the box, this is it. - **Pros:** Extremely feature-rich, great documentation. - **Cons:** Higher price point, can be overkill for simple projects. ### 3. Nuxt Beyond Considered one of the top **Nuxt boilerplate alternatives**, **Nuxt Beyond** ([nuxtbeyond.com](https://nuxtbeyond.com/){rel=""nofollow""}) offers a robust, full-stack framework configured specifically for Nuxt ecosystem enthusiasts wanting extensive built-in capabilities. - **Pros:** Great baseline for full-stack applications. - **Best For:** Developers looking for a comprehensive, structured foundation. ### 4. Nuxt SaaS Kit A solid, middle-of-the-road option that has been around for a while. It's a reliable **nuxt js starter kit** for those using Prisma and standard relational databases. - **Pros:** Well-tested, great blog integration. --- ## How to Choose a Pre-configured solution for Web Development When you **compare popular Nuxt starter kits for beginners**, look beyond just the price. Ask these questions: 1. **Nuxt 4 Support:** Is the kit updated for the latest major version? 2. **Database Choice:** Do you prefer the simplicity of Supabase, or the control of Drizzle/Prisma? 3. **UI Library:** Does it use Nuxt UI, Tailwind, or something else you are comfortable with? 4. **Maintenance:** How often is the kit updated? --- ## FAQ: Nuxt Starter Kits & Rapid Development ### What is the best Nuxt starter kit for beginners? For beginners, the **official Nuxt UI starter** or **ShipAhead** are great because they have clean codebases and excellent documentation. ### Why choose a Nuxt 4 starter kit over Nuxt 3? **Nuxt 4 starter kits** offer better performance, a more refined folder structure (`app/` directory), and better typing support. It is always better to start with the latest version in 2026. ### Are there affordable Nuxt starter kits with built-in features? Yes, kits like **ShipAhead** and **NuxSaaS** offer lifetime licenses for under $150, which is a fraction of the cost of building these features manually. ### How do I choose between Nuxt UI and other UI kits? Choose a **nuxt ui starter kit** if you want the most integrated experience with the Nuxt ecosystem. It is built by the Nuxt team and follows all their best practices. --- ## Conclusion: Start Building Today The **best options for quickly starting a new web project** in 2026 all point towards using a high-quality boilerplate. Stop fighting with configurations and start shipping features. Ready to launch your next big idea? [Get ShipAhead](https://shipahe.ad){rel=""nofollow""} and join the founders who are building the future with Nuxt 4. # How to Upgrade Nuxt 3 to 4 in Under 10 Minutes – A Clear Guide Nuxt 4 is a massive shift in how we build and structure Vue apps. While major version updates can feel like a headache, staying on Nuxt 3 is just building up tech debt you’ll have to pay later. The jump to Nuxt 4 brings better performance, a cleaner `app/` directory, and a much tighter developer experience. Here is the no-nonsense migration guide to get your project upgraded in under 10 minutes. --- ## Why Should You Migrate to Nuxt 4 Now? Waiting to **modernize your Nuxt app** only makes it harder as your codebase grows. By upgrading now, you get: - **The "app/" Directory:** A much cleaner root folder that separates your business logic from your configuration. - **Improved Type Safety:** Better error catching while you write code. - **Faster Cold Starts:** Your development environment will feel snappier. --- ## Step 1: Update Your Dependencies The first step is to pull in the latest Nuxt package. Open your terminal and run: ```bash # Using npm npm install nuxt@latest # Using pnpm pnpm add nuxt@latest ``` This ensures you have the latest core binaries ready to handle the transformation. --- ## Step 2: Enable the Nuxt 4 Compatibility Version Nuxt 4 allows you to transition gradually. In your `nuxt.config.ts` file, you can set the compatibility version to `4`. This prepares your project for the new behaviors. ```typescript export default defineNuxtConfig({ future: { compatibilityVersion: 4, }, }); ``` --- ## Step 3: Shift to the New Directory Structure The biggest change in Nuxt 4 is the **Nuxt 4 directory structure**. Instead of having `pages/`, `components/`, and `composables/` in the root, they now live inside an `app/` folder. 1. Create an `app/` folder in your root directory. 2. Move your `pages/`, `layouts/`, `components/`, `composables/`, `middleware/`, and `plugins/` folders into it. 3. Rename `app.vue` to `app/app.vue` (if applicable). This separation keeps your root directory clean and focused on environment configuration. --- ## Step 4: Handle Nuxt 4 Breaking Changes While the migration tool handles most of the heavy lifting, you should manually check for common **Nuxt 4 breaking changes**: - **Scanning Changes:** Nuxt 4 is more strict about where it looks for files. If you have custom directories, you may need to register them in your config. - **Imports:** Ensure you aren't using deep imports from internal Nuxt packages that may have moved. - **Layer Compatibility:** If you use Nuxt Layers, ensure they also have the `compatibilityVersion: 4` flag. --- ## Step 5: Test and Verify Now, fire up your development server. ```bash npm run dev ``` Watch the terminal for any warnings or errors. If everything looks good, run your build command to ensure the production bundle is also generated without issues. --- ## Ready for a Fresh Start? If your Nuxt 3 project is too messy to upgrade, sometimes a fresh start is the best path forward. [ShipAhead](https://shipahe.ad){rel=""nofollow""} is built from the ground up on Nuxt 4. It includes all the best practices, the new directory structure, and modern auth integrated out of the box. Skip the migration headache and start building with the latest technology today. --- ## Final Thoughts The jump to Nuxt 4 is a major step forward for the Vue ecosystem. It simplifies your project and prepares you for the next few years of web development. Don't let your tech debt stay high—**Upgrade Nuxt 3 to 4** today and enjoy a faster development workflow. # Vibe Coding Your SaaS – The Modern Way to Build in 2026 Most of my best work happens when I'm not "grinding." It happens when I'm in a flow state, moving fast, and seeing my ideas come to life in real-time. Lately, the indie hacker community has been calling this **Vibe Coding**. It’s the opposite of the "Architecture Astronaut" approach where you spend weeks planning. Instead, you prioritize intuition and speed, using AI and pre-built stacks to handle the execution while you focus on the vision. Here’s how I use this workflow to ship faster than I ever could by hand. --- ## What Exactly is "Vibe Coding"? Vibe coding is a style of **intuitive software development** where you focus on the vision while AI and boilerplates handle the execution. You describe what you want, you experiment in real-time, and you let the app grow naturally. The core rules of vibe coding are: - **No Starting from Zero:** You never start with an empty folder. - **High-Context AI:** You use tools that understand your whole project. - **Rapid Feedback:** You see changes instantly and iterate based on "the vibe." --- ## Why Flow State is Your Competitive Advantage The biggest threat to your SaaS is boredom. If you spend three days trying to connect a database, you lose your momentum. **Building a SaaS in flow** means you never hit those "wall" moments that make you want to quit. To maintain these **modern development vibes**, you need a stack that doesn't get in your way. ### Step 1: Secure the Foundation You cannot "vibe" if you are writing login logic. Use [ShipAhead](https://shipahe.ad){rel=""nofollow""} to get the infrastructure out of the way. It provides a clean, pre-configured Nuxt 4 environment that is ready for your ideas. ### Step 2: Leverage AI Agents Tools like **Cursor** and **Claude** are the engines behind **vibe coding**. When you use a structured boilerplate, the AI knows exactly where things should go. You don't "write code"; you "guide the AI" through the project. --- ## How ShipAhead Enables Efficient SaaS Building We designed [ShipAhead](https://shipahe.ad){rel=""nofollow""} specifically for the vibe-coding era. It is not just a bunch of files; it is a system designed for maximum velocity. - **AI-Native Architecture:** Folders and files are named logically so AI coding agents can navigate your project without mistakes. - **Pre-styled Components:** Use our Tailwind library to build beautiful pages by simply describing them to the AI. - **Zero-Config Deployments:** One click and your "vibe" is live for the world to see. --- ## The Secret to Moving Fast Most founders move slowly because they are perfectionists about the wrong things. They spend weeks on a database schema that will change anyway. Vibe coding encourages you to ship the MVP (Minimum Viable Vibe) first. Get it live, see how it feels, and then refine. This is the heart of **efficient SaaS building**. --- ## Conclusion The future of software isn't just about "writing code." It is about having the best ideas and the best flow. If you want to experience the true power of **Vibe Coding SaaS**, stop wasting time on the setup. Grab [ShipAhead](https://shipahe.ad){rel=""nofollow""}, fire up your AI assistant, and build your business in the zone. Your best ideas are waiting. Start shipping.