Skip to content

Commit 604cbdf

Browse files
committed
2 parents b9afbee + b3eb772 commit 604cbdf

6 files changed

Lines changed: 112 additions & 30 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Supabase Heartbeat
2+
3+
on:
4+
schedule:
5+
# Run daily at 12:00 UTC to keep the Supabase function alive
6+
- cron: '0 12 * * *'
7+
workflow_dispatch: # Allow manual triggering
8+
9+
jobs:
10+
heartbeat:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Send heartbeat to Supabase function
15+
run: |
16+
# Replace with your actual Supabase function URL
17+
SUPABASE_URL="${{ secrets.SUPABASE_FUNCTION_URL }}"
18+
19+
if [ -z "$SUPABASE_URL" ]; then
20+
echo "SUPABASE_FUNCTION_URL secret not set. Please add your Supabase function URL as a repository secret."
21+
echo "The URL should be in the format: https://your-project-id.supabase.co/functions/v1/stripe-webhook"
22+
exit 1
23+
fi
24+
25+
echo "Sending heartbeat to Supabase function..."
26+
27+
# Send heartbeat request with query parameter
28+
RESPONSE=$(curl -s -w "%{http_code}" -o response_body.txt \
29+
-X GET \
30+
"${SUPABASE_URL}?heartbeat=true" \
31+
-H "Authorization: Bearer ${{ secrets.SUPABASE_ANON_KEY }}" \
32+
-H "x-heartbeat: true")
33+
34+
HTTP_CODE="${RESPONSE}"
35+
RESPONSE_BODY=$(cat response_body.txt)
36+
37+
echo "HTTP Status Code: $HTTP_CODE"
38+
echo "Response Body: $RESPONSE_BODY"
39+
40+
if [ "$HTTP_CODE" -eq 200 ]; then
41+
echo "✅ Heartbeat successful - Supabase function is alive!"
42+
else
43+
echo "❌ Heartbeat failed with status code: $HTTP_CODE"
44+
echo "Response: $RESPONSE_BODY"
45+
exit 1
46+
fi

src/components/LighthouseSection.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,8 @@ const LighthouseSection = () => {
254254
<p className="text-xs text-muted-foreground mt-4">Base Version Free forever • All Code is Open Source • Everything runs on your Infrstructure - No Third-Party Cloud Services involved</p>
255255
</div>
256256

257-
{/* Testimonials Slider
257+
{/* Testimonials Slider */}
258258
<LighthouseTestimonials />
259-
*/}
260259
</div>
261260
</section>
262261
);

src/components/LighthouseTestimonials.tsx

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ChevronLeft, ChevronRight, ExternalLink } from "lucide-react";
2-
import { useState } from "react";
2+
import { useState, useMemo } from "react";
33
import { Card, CardContent } from "@/components/ui/card";
44

55
export interface Testimonial {
@@ -13,40 +13,48 @@ export interface Testimonial {
1313

1414
const testimonials: Testimonial[] = [
1515
{
16-
quote: "Lighthouse transformed how we understand and optimize our team's workflow. The insights are invaluable.",
16+
quote: "The ability of Lighthouse to continuous forecast is a game changer. It transforms something complex and time consuming in a continuous activity which enlightens both your project planning and tracking.",
17+
author: "Lorenzo Santoro",
18+
role: "Project Manager",
19+
company: "",
20+
authorUrl: "https://www.linkedin.com/in/lorenzo-santoro-57172626/",
21+
companyUrl: ""
22+
},
23+
{
24+
quote: "",
1725
author: "Agnieszka Reginek",
1826
role: "Professional Kanban Trainer | Scrum Master",
1927
company: "",
2028
authorUrl: "https://www.linkedin.com/in/agnieszka-reginek/",
2129
companyUrl: ""
2230
},
2331
{
24-
quote: "The real-time flow metrics helped us identify bottlenecks we never knew existed. Productivity up 40%.",
25-
author: "Michael Chen",
26-
role: "Product Director",
27-
company: "InnovateLab",
28-
authorUrl: "https://linkedin.com/in/michael-chen",
29-
companyUrl: "https://innovatelab.com"
32+
quote: "Lighthouse has transformed how we approach delivery. By prompting the right questions earlier and using the default feature size function to quickly forecast “how much?”, it provides a lean, cost‑effective way to surface risk and enable better decisions.",
33+
author: "Chris Graves",
34+
role: "Agile Coach",
35+
company: "Focusrite",
36+
authorUrl: "https://www.linkedin.com/in/chris-graves-23455ab8/",
37+
companyUrl: "https://focusrite.com/"
3038
},
3139
{
32-
quote: "Finally, data-driven decisions instead of gut feelings. Our forecasting accuracy improved dramatically.",
33-
author: "Emma Rodriguez",
34-
role: "Agile Coach",
35-
company: "FlowTech Solutions",
36-
authorUrl: "https://linkedin.com/in/emma-rodriguez"
40+
quote: "Lighthouse helped us be more on to it. We’re now more predictable, efficient, and responsive when it comes to delivering value and serving our customers. It’s made planning sessions run smoother and helped set clearer expectations with our stakeholders. The insights we get from the data really sharpen our conversations and keep us focused on what matters.",
41+
author: "Gonzalo Mendez",
42+
role: "Scrum Master",
43+
authorUrl: "https://www.linkedin.com/in/gonzalo-mendez-nz/",
44+
company: "Mitre 10 (New Zealand) Ltd.",
45+
companyUrl: "https://www.mitre10.co.nz/"
3746
},
3847
{
39-
quote: "The Swiss quality and privacy standards give us confidence in using Lighthouse for sensitive projects.",
40-
author: "Hans Mueller",
41-
role: "CTO",
42-
company: "SecureFlow AG",
43-
companyUrl: "https://secureflow.ch"
48+
quote: "",
49+
author: "Gábor Bittera",
50+
role: "VP Engineering",
51+
authorUrl: "https://www.linkedin.com/in/gaborbittera/"
4452
},
4553
{
46-
quote: "Open source core with premium enterprise features - exactly what we needed for our scaling organization.",
47-
author: "Lisa Wang",
54+
quote: "",
55+
author: "Hendra Gunawan",
4856
role: "VP Engineering",
49-
authorUrl: "https://linkedin.com/in/lisa-wang"
57+
authorUrl: "https://www.linkedin.com/in/hendragunawan823/"
5058
}
5159
];
5260

@@ -134,14 +142,27 @@ const NavigationButton = ({
134142
);
135143

136144
const LighthouseTestimonials = () => {
145+
// Filter out testimonials with empty quotes and shuffle on every component load
146+
const shuffledTestimonials = useMemo(() => {
147+
const validTestimonials = testimonials.filter(testimonial =>
148+
testimonial.quote && testimonial.quote.trim() !== ''
149+
);
150+
const shuffled = [...validTestimonials];
151+
for (let i = shuffled.length - 1; i > 0; i--) {
152+
const j = Math.floor(Math.random() * (i + 1));
153+
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
154+
}
155+
return shuffled;
156+
}, []);
157+
137158
const [currentTestimonial, setCurrentTestimonial] = useState(0);
138159

139160
const nextTestimonial = () => {
140-
setCurrentTestimonial((prev) => (prev + 1) % testimonials.length);
161+
setCurrentTestimonial((prev) => (prev + 1) % shuffledTestimonials.length);
141162
};
142163

143164
const prevTestimonial = () => {
144-
setCurrentTestimonial((prev) => (prev - 1 + testimonials.length) % testimonials.length);
165+
setCurrentTestimonial((prev) => (prev - 1 + shuffledTestimonials.length) % shuffledTestimonials.length);
145166
};
146167

147168
const title = "See What Lighthouse Users Are Saying";
@@ -155,7 +176,7 @@ const LighthouseTestimonials = () => {
155176
</div>
156177

157178
<div className="relative max-w-4xl mx-auto">
158-
<TestimonialCard testimonial={testimonials[currentTestimonial]} />
179+
<TestimonialCard testimonial={shuffledTestimonials[currentTestimonial]} />
159180

160181
<NavigationButton
161182
onClick={prevTestimonial}
@@ -168,7 +189,7 @@ const LighthouseTestimonials = () => {
168189

169190
{/* Dots indicator */}
170191
<div className="flex justify-center space-x-2 mt-6">
171-
{testimonials.map((testimonial, testimonialIndex) => (
192+
{shuffledTestimonials.map((testimonial, testimonialIndex) => (
172193
<button
173194
key={`dot-${testimonial.author}`}
174195
onClick={() => setCurrentTestimonial(testimonialIndex)}

src/components/Navigation.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const Navigation = () => {
1919

2020
const lighthouseSubItems = [
2121
{ name: "Overview", href: "#lighthouse-overview" },
22-
//{ name: "Testimonials", href: "#lighthouse-testimonials" },
22+
{ name: "Testimonials", href: "#lighthouse-testimonials" },
2323
{ name: "Lighthouse Premium", href: "#lighthouse-premium" },
2424
{ name: "Get a License", href: "#lighthouse-license" },
2525
{ name: "Key Features", href: "#lighthouse-features" },

src/pages/Lighthouse.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,13 +496,12 @@ const Lighthouse = () => {
496496
</div>
497497
</section>
498498

499-
{/* Testimonials Section DONT FORGET TO ENABLE THE NAVIGATION LINK AGAIN
499+
{/* Testimonials Section */}
500500
<section id="lighthouse-testimonials" className="py-20 bg-background">
501501
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
502502
<LighthouseTestimonials />
503503
</div>
504504
</section>
505-
*/}
506505

507506
{/* Why Premium Section */}
508507
<section id="lighthouse-premium" className="py-20 bg-gradient-subtle">

supabase/functions/stripe-webhook/index.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,23 @@ serve(async (req)=>{
1111
headers: corsHeaders
1212
});
1313
}
14+
15+
// Handle heartbeat requests to keep the function alive
16+
const url = new URL(req.url);
17+
if (url.searchParams.get('heartbeat') === 'true' || req.headers.get('x-heartbeat') === 'true') {
18+
console.log("Heartbeat request received - keeping function alive");
19+
return new Response(JSON.stringify({
20+
status: 'alive',
21+
timestamp: new Date().toISOString()
22+
}), {
23+
headers: {
24+
...corsHeaders,
25+
"Content-Type": "application/json"
26+
},
27+
status: 200
28+
});
29+
}
30+
1431
try {
1532
const stripe = new Stripe(Deno.env.get("STRIPE_SECRET_KEY") || "", {
1633
apiVersion: "2023-10-16"

0 commit comments

Comments
 (0)