Skip to content

Commit 9ce1098

Browse files
committed
Initial commit
0 parents  commit 9ce1098

File tree

99 files changed

+11833
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+11833
-0
lines changed

.eslintrc.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": ["next/core-web-vitals", "eslint:recommended"],
3+
"env": {
4+
"browser": true,
5+
"node": true,
6+
"es6": true
7+
},
8+
"rules": {
9+
// Your specific rules.
10+
"no-unused-vars": "warn"
11+
}
12+
}

.gitignore

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# next.js
12+
/.next/
13+
/out/
14+
15+
# production
16+
/build
17+
18+
# misc
19+
.DS_Store
20+
*.pem
21+
22+
# debug
23+
npm-debug.log*
24+
yarn-debug.log*
25+
yarn-error.log*
26+
27+
# local env files
28+
.env*.local
29+
30+
# vercel
31+
.vercel
32+
33+
# typescript
34+
*.tsbuildinfo
35+
next-env.d.ts
36+
37+
# public
38+
public/robots.txt
39+
public/sitemap.xml
40+
public/sitemap-0.xml

.vscode/settings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{
2+
}

README.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# 🚀 WantShip - Javascript
2+
3+
**Welcome to WantShip!** 👋
4+
Thank you for choosing WantShip as your go-to boilerplate for building, shipping, and monetizing your SaaS application quickly and efficiently. We’re thrilled to have you on board!
5+
6+
## 🎉 Quick Start Guide
7+
8+
Follow these steps to get your app up and running in no time:
9+
10+
### 1. Clone the Repository
11+
12+
Open your terminal and run the following commands:
13+
14+
```bash
15+
git clone https://github.com/Techiral/WantShip.git [YOUR_APP_NAME]
16+
cd [YOUR_APP_NAME]
17+
git checkout supabase
18+
npm install
19+
git remote remove origin
20+
npm run dev
21+
```
22+
23+
> **Note:**
24+
> WantShip requires **Node 18.17** or greater. Check your Node version with:
25+
> ```bash
26+
> node -v
27+
> ```
28+
29+
- **Main Branch:** Includes default NextAuth/MongoDB features.
30+
- **Supabase Branch:** Includes Supabase/PostgreSQL features.
31+
32+
### 2. Configure Environment Variables
33+
34+
Rename the `.env.example` file to `.env.local`:
35+
36+
```bash
37+
mv .env.example .env.local
38+
```
39+
40+
Open `.env.local` and add your Supabase environment variables:
41+
42+
```env
43+
NEXT_PUBLIC_SUPABASE_URL=
44+
NEXT_PUBLIC_SUPABASE_ANON_KEY=
45+
SUPABASE_SERVICE_ROLE_KEY=
46+
EMAIL_SERVER=
47+
MAILGUN_API_KEY=
48+
STRIPE_PUBLIC_KEY=
49+
STRIPE_SECRET_KEY=
50+
STRIPE_WEBHOOK_SECRET=
51+
```
52+
53+
### 3. Set Up Supabase
54+
55+
1. Go to the [Supabase Dashboard](https://supabase.com/dashboard).
56+
2. Create a new project.
57+
3. Copy your **Supabase URL** and **Anon Key**.
58+
4. Paste them into the corresponding fields in `.env.local`.
59+
60+
### 4. Launch Your Local Server
61+
62+
Start your development server:
63+
64+
```bash
65+
npm run dev
66+
```
67+
68+
Open [http://localhost:3000](http://localhost:3000) in your browser to see your site.
69+
*You might see some console errors initially, but nothing critical!*
70+
71+
## 📂 Project Structure
72+
73+
- **/app** → Pages (1 folder + `page.js` = 1 page)
74+
- **/app/api** → API calls (1 file = 1 API endpoint)
75+
- **/components** → React components
76+
- **/libs** → Libraries and helper functions (Stripe, Mailgun, auth, etc.)
77+
- **config.js** → Configuration file. Each key is documented to explain its purpose.
78+
*This is the backbone of your app.*
79+
80+
## ✨ Customize Your App
81+
82+
### Edit the Landing Page
83+
84+
1. Delete everything in `/app/page.js`.
85+
2. Replace it with the following code:
86+
87+
```javascript
88+
import { Suspense } from 'react'
89+
import Header from "@/components/Header";
90+
import Hero from "@/components/Hero";
91+
import Problem from "@/components/Problem";
92+
import FeaturesAccordion from "@/components/FeaturesAccordion";
93+
import Pricing from "@/components/Pricing";
94+
import FAQ from "@/components/FAQ";
95+
import CTA from "@/components/CTA";
96+
import Footer from "@/components/Footer";
97+
98+
export default function Home() {
99+
return (
100+
<>
101+
<Suspense>
102+
<Header />
103+
</Suspense>
104+
<main>
105+
<Hero />
106+
<Problem />
107+
<FeaturesAccordion />
108+
<Pricing />
109+
<FAQ />
110+
<CTA />
111+
</main>
112+
<Footer />
113+
</>
114+
);
115+
}
116+
```
117+
118+
3. **Customize Your Content:**
119+
- Edit each component (`Header`, `Hero`, `Problem`, etc.) to fit your business logic.
120+
- Each component includes tips to help you write copy that sells.
121+
122+
> **Congratulations!** 🎉
123+
> You now have a beautiful landing page to showcase your SaaS application.
124+
125+
### (Optional) Collect Emails for a Waitlist
126+
127+
1. Set up a database.
128+
2. Replace the main call-to-action buttons in the following components:
129+
130+
**Hero.js & CTA.js:**
131+
132+
```javascript
133+
import ButtonLead from "@/components/ButtonLead";
134+
135+
{/* Replace the CTA button with this */}
136+
<ButtonLead />
137+
```
138+
139+
**Pricing.js:**
140+
141+
```javascript
142+
import ButtonLead from "@/components/ButtonLead";
143+
144+
{/* Replace the Pricing CTA button with this */}
145+
<ButtonLead extraStyle="!max-w-none !w-full" />
146+
```
147+
148+
## 🚀 Deploy Your App
149+
150+
It’s time to take your app live! Follow our simple [deployment tutorial](https://10x-ship.vercel.app/blog) to get your startup in front of your customers within 5 minutes.
151+
*Need more help?* Check out our comprehensive [documentation](https://10x-ship.vercel.app/blog).
152+
153+
## 📚 Additional Resources
154+
155+
- **Documentation:** [WantShip Blog](https://10x-ship.vercel.app/blog)
156+
- **Stay Updated:** [Subscribe to our Newsletter](https://techiral.beehiiv.com/)
157+
- **Follow Us on Twitter:** [@techiral_](https://twitter.com/techiral_)
158+
159+
## 🙌 Thank You!
160+
161+
Thank you for choosing WantShip! We’re excited to see what you build. If you have any questions or need support, feel free to reach out through our [Twitter](https://twitter.com/techiral_) or subscribe to our [newsletter](https://techiral.beehiiv.com/) for the latest updates and tips.
162+
163+
**Let’s build that startup, FAST ⚡️**
164+
165+
---
166+
167+
**WantShip - Build. Ship. Monetize.**

app/2.jfif

156 KB
Binary file not shown.

app/3.jfif

135 KB
Binary file not shown.

app/One.jfif

135 KB
Binary file not shown.

app/Supabase.png

1.05 MB
Loading
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// import Link from "next/link";
2+
// This is the article card that appears in the home page, in the category page, and in the author's page
3+
// const UserSurveyID = ({surveyObject}) => {
4+
5+
// return (
6+
// <div>
7+
// {{surveyObject}}
8+
// </div>
9+
// )
10+
// }

app/[...survey]/page.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
'use client';
2+
import React, { useState,useEffect } from 'react';
3+
import { useRouter } from 'next/navigation'
4+
import axios from 'axios';
5+
export default function Page({ params }) {
6+
const { survey } = params;
7+
const router = useRouter()
8+
const id = survey[1]
9+
const [data,setData] = useState([]);
10+
const fetchData = async () => {
11+
const result = await axios.get('/api/public/getPublic/', { params: {
12+
id: id
13+
}})
14+
// Check if result.data is an array
15+
if (Array.isArray(result.data.data)) {
16+
setData(result.data.data);
17+
} else {
18+
console.error(typeof result.data.data)
19+
console.error('Error: result.data is not an array');
20+
}
21+
};
22+
23+
useEffect(() => {
24+
fetchData();
25+
}, []);
26+
27+
const voteSurvey = async (id) => {
28+
try {
29+
const response = await axios.post('/api/public/votePublic', {params: {id}});
30+
router.push('/thankyou');
31+
fetchData();
32+
} catch (error) {
33+
console.error(error);
34+
}
35+
}
36+
37+
return(
38+
<div className='flex flex-col items-center justify-center min-h-screen'>
39+
<div>
40+
{data.map((item, index) => (
41+
<h1 className='text-xl text-center uppercase mb-3 ' key={index}>
42+
{item.title}
43+
</h1>
44+
))}
45+
</div>
46+
47+
<div>
48+
<table className='table'>
49+
<tbody>
50+
<tr>
51+
{data.map((item, index) => (
52+
<td className='bg-base-200' key={item.id} onClick={() => voteSurvey({"user_selected":"option_1","survey_id":id})}>{item.option_1}</td>
53+
))}
54+
</tr>
55+
<tr>
56+
{data.map((item, index) => (
57+
<td className='bg-base-200' key={item.id} onClick={() => voteSurvey({"user_selected":"option_2","survey_id":id})}>{item.option_2}</td>
58+
))}
59+
</tr>
60+
<tr>
61+
{data.map((item, index) => (
62+
<td className='bg-base-200' key={item.id} onClick={() => voteSurvey({"user_selected":"option_3","survey_id":id})}>{item.option_3}</td>
63+
))}
64+
</tr>
65+
<tr>
66+
{data.map((item, index) => (
67+
<td className='bg-base-200' key={item.id} onClick={() => voteSurvey({"user_selected":"option_4","survey_id":id})}>{item.option_4}</td>
68+
))}
69+
</tr>
70+
</tbody>
71+
</table>
72+
</div>
73+
</div>
74+
)
75+
}

app/api/auth/callback/route.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
2+
import { cookies } from "next/headers";
3+
import { NextResponse } from "next/server";
4+
import config from "@/config";
5+
6+
export const dynamic = "force-dynamic";
7+
8+
// This route is called after a successful login. It exchanges the code for a session and redirects to the callback URL (see config.js).
9+
export async function GET(req) {
10+
const requestUrl = new URL(req.url);
11+
const code = requestUrl.searchParams.get("code");
12+
13+
if (code) {
14+
const supabase = createRouteHandlerClient({ cookies });
15+
await supabase.auth.exchangeCodeForSession(code);
16+
}
17+
18+
// URL to redirect to after sign in process completes
19+
return NextResponse.redirect(requestUrl.origin + config.auth.callbackUrl);
20+
}

app/api/lead/route.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { NextResponse } from "next/server";
2+
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
3+
import { cookies } from "next/headers";
4+
5+
// This route is used to store the leads that are generated from the landing page.
6+
// The API call is initiated by <ButtonLead /> component
7+
export async function POST(req) {
8+
const body = await req.json();
9+
10+
if (!body.email) {
11+
return NextResponse.json({ error: "Email is required" }, { status: 400 });
12+
}
13+
14+
try {
15+
const supabase = createRouteHandlerClient({ cookies });
16+
await supabase.from("leads").insert({ email: body.email });
17+
18+
return NextResponse.json({});
19+
} catch (e) {
20+
console.error(e);
21+
return NextResponse.json({ error: e.message }, { status: 500 });
22+
}
23+
}

app/api/public/getPublic/route.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
2+
import { NextResponse } from "next/server";
3+
import { cookies } from "next/headers";
4+
5+
export const dynamic = "force-dynamic";
6+
7+
export async function GET(req,res, next) {
8+
const id = req.nextUrl.searchParams.get("id");
9+
const supabase = createRouteHandlerClient({ cookies });
10+
11+
const { data, error } = await supabase.from("user_created_polls").select("*").eq("id", id);
12+
if (error) {
13+
return NextResponse.json({ "error": error.message }, { status: 500 });
14+
}
15+
return NextResponse.json({ "data": data}, { status: 200 });
16+
}
17+

0 commit comments

Comments
 (0)