Which landing page is this?
apps/web/- Your app’s marketing page (this guide)landing_page/- Shipnative’s own marketing site (not yours)
Two Modes
The marketing page has two modes you can switch between:Waitlist Mode (Pre-Launch)
Perfect for collecting early user emails before your app launches. Features:- Email capture form with validation
- Success confirmation message
- App screenshot showcase
- Feature bento grid with 6 tiles:
- AI-first architecture
- Mock mode
- Premium design system
- Monetization
- Analytics & reliability
- Optimized dev loop
- AI tools integration section (Cursor, Claude, Copilot, etc.)
- Fully responsive design
- SEO optimized
Launch Mode (Post-Launch)
Perfect for when your app is live on the App Store and Google Play. Features:- App Store and Google Play badge links
- Hero section with app name and tagline
- Feature highlights (3 key benefits)
- Clean, minimal design focused on downloads
- SEO optimized
️ Quick Setup
yarn setup now also asks for the marketing page mode. It writes apps/web/.env for you, so you can skip to Step 3 if you just ran it.Important: The Resend API key is now stored securely in Supabase Edge Function secrets, not in the frontend .env file. See the “Adding a Waitlist API” section below for setup instructions.Step 1: Copy Environment Variables (if you skipped yarn setup)
Step 2: Configure Your Settings
Editapps/web/.env (or let yarn setup fill it):
Step 3: Switch Modes Quickly
Step 4: Run the Development Server
http://localhost:5173 to see your marketing page!
Customization
Switching Between Modes
Use the helper command (it updatesapps/web/.env for you):
VITE_MODE in apps/web/.env. No code changes needed - the app automatically renders the correct mode!
Customizing Waitlist Mode
Edit/apps/web/src/components/WaitlistMode.tsx:
Change feature tiles (lines 92-164):
- Place your screenshot in
/apps/web/public/app-screenshot.png - Or update
VITE_APP_SCREENSHOT_URLto use a URL
Customizing Launch Mode
Edit/apps/web/src/components/LaunchMode.tsx:
Change feature highlights (lines 92-108):
- Colors:
bg-blue-600,text-gray-900, etc. - Spacing:
p-4,m-8,gap-6, etc. - Layout: Grid, flex, responsive breakpoints
Adding a Waitlist API with Supabase Edge Function
The waitlist form is already configured to use a Supabase Edge Function endpoint. This keeps your Resend API key secure on the server side. Step 1: Create the Waitlist Table The waitlist table SQL is already included insupabase/schema.sql. You have two options:
Option A: Run the full schema (Recommended)
If you haven’t set up your Supabase database yet, run the entire supabase/schema.sql file in your Supabase SQL Editor. It includes the waitlist table along with all other default tables.
Option B: Run just the waitlist table SQL
If you’ve already set up your database and just need the waitlist table, run this SQL in your Supabase SQL Editor:
- Install Supabase CLI (if not already installed):
- Login to Supabase:
- Link your project:
- Initialize Supabase in your project (if not already done):
- Create the edge function:
supabase/functions/waitlist/index.ts. Replace its contents with this code:
- Deploy the edge function:
- Set environment secrets in Supabase Dashboard:
- Go to Project Settings → Edge Functions → Secrets
- Add
RESEND_API_KEY(your Resend API key) - Add
RESEND_FROM_EMAIL(optional, e.g.,noreply@yourdomain.com) - Add
RESEND_WAITLIST_SUBJECT(optional, custom subject line) - Add
RESEND_WAITLIST_HTML(optional, custom HTML email template)
apps/web/.env:
your-project-ref with your actual Supabase project reference (found in your Supabase dashboard URL).
That’s it! The waitlist form will now:
- Save emails to your Supabase database
- Send confirmation emails via Resend (if configured)
- Keep your Resend API key secure on the server
Deployment
Deploy to Vercel (Recommended)
- Push your code to GitHub
- Go to vercel.com
- Import your repository
- Set Root Directory to
apps/web - Add environment variables from your
.envfile - Deploy!
vercel.json configuration file for easy deployment.
Deploy to Netlify
- Go to netlify.com
- Import your repository
- Set Base directory to
apps/web - Set Build command to
yarn build - Set Publish directory to
apps/web/dist - Add environment variables
- Deploy!
Other Platforms
The marketing page is a standard Vite app, so it works with:- Cloudflare Pages
- GitHub Pages
- AWS Amplify
- Any static host
yarn build (from apps/web/)
Output directory: dist/
SEO Configuration
The landing page includes SEO components that set:- Meta title and description
- Open Graph tags (for social sharing)
- Twitter cards
- Canonical URL
.env:
/apps/web/public/og-image.jpg.
vs. Main Landing Page Repo
You might be wondering: “What’s the difference betweenapps/web and the landing_page repo?”
| Feature | apps/web | landing_page |
|---|---|---|
| Purpose | Your app’s marketing page | Shipnative’s own marketing |
| Included | Yes, in the monorepo | Separate repository |
| Customization | You own it - edit freely | Don’t edit (it’s for Shipnative) |
| Use case | Pre-launch waitlist or launch page | Shipnative product marketing |
| Deploy | Your domain | shipnative.com |
apps/web for YOUR app. Ignore landing_page (unless you’re contributing to Shipnative itself).
Tips & Best Practices
Pre-Launch Strategy
- Start in waitlist mode while building
- Share the link on Twitter, Product Hunt, Reddit
- Collect 100-1000+ emails before launch
- Send launch announcement when app goes live
Launch Day
- Switch to launch mode (
VITE_MODE=launch) - Add your App Store / Play Store URLs
- Redeploy
- Email your waitlist!
A/B Testing
Want to test different copy? Create multiple deployments:waitlist-v1.yourapp.comwaitlist-v2.yourapp.com
Custom Domain
- Buy a domain (Namecheap, Google Domains, etc.)
- Point it to your Vercel/Netlify deployment
- Configure in your hosting dashboard
- Update
VITE_APP_URLto match
Troubleshooting
Environment variables not working
Environment variables not working
- Make sure your
.envfile is inapps/web/, not the monorepo root - Restart the dev server after changing
.env - Vite requires
VITE_prefix for all public env vars - Check for typos in variable names
App screenshot not showing
App screenshot not showing
- Verify the image exists in
/apps/web/public/ - Check that
VITE_APP_SCREENSHOT_URLmatches your filename - Try using an absolute URL instead of a relative path
- Clear browser cache
Waitlist form not submitting
Waitlist form not submitting
- Check browser console for errors
- Verify
VITE_WAITLIST_API_ENDPOINTis correctly set - Test your API endpoint with Postman/Insomnia first
- Check CORS settings on your API
Styling looks broken
Styling looks broken
- Run
yarn installinapps/web/ - Verify
tailwind.config.cjsexists - Check that
src/index.cssis imported insrc/main.tsx - Try
yarn buildto see if it’s a dev-only issue

