diff --git a/public/assets/images/deployapp-thumb.jpg b/public/assets/images/services/deployapp-thumb.jpg similarity index 100% rename from public/assets/images/deployapp-thumb.jpg rename to public/assets/images/services/deployapp-thumb.jpg diff --git a/public/assets/images/services/kubernetes-edge.png b/public/assets/images/services/kubernetes-edge.png new file mode 100644 index 0000000..93b9aaf Binary files /dev/null and b/public/assets/images/services/kubernetes-edge.png differ diff --git a/public/assets/node-js.jpg b/public/assets/images/services/node-js.jpg similarity index 100% rename from public/assets/node-js.jpg rename to public/assets/images/services/node-js.jpg diff --git a/public/assets/images/services/stt-streaming.png b/public/assets/images/services/stt-streaming.png new file mode 100644 index 0000000..3c0912e Binary files /dev/null and b/public/assets/images/services/stt-streaming.png differ diff --git a/public/assets/images/wiregurd-thumb.jpg b/public/assets/images/services/wiregurd-thumb.jpg similarity index 100% rename from public/assets/images/wiregurd-thumb.jpg rename to public/assets/images/services/wiregurd-thumb.jpg diff --git a/src/components/BuyServices/STTStreaming.jsx b/src/components/BuyServices/STTStreaming.jsx new file mode 100644 index 0000000..c1ce815 --- /dev/null +++ b/src/components/BuyServices/STTStreaming.jsx @@ -0,0 +1,114 @@ +import React, { useState } from 'react'; +import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '../ui/card'; +import { Button } from '../ui/button'; +import { useIsLoggedIn } from '../../lib/isLoggedIn'; +import Loader from "../ui/loader"; +import { Loader2 } from "lucide-react"; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "../ui/dialog"; +const PRICE_CONFIG = [ + {purchaseType: 'loose', price: 2000, minute: 10000}, + {purchaseType: 'bulk', price: 1000, minute: 10000} +]; +export default function STTStreaming(){ + const USER_API_URL = 'https://host-api.cs1.hz.siliconpin.com/v1/users/'; + const [purchaseType, setPurchaseType] = useState(); + const [amount, setAmount] = useState(); + const [dataError, setDataError] = useState(); + const [isProcessing, setIsProcessing] = useState(false); + const handlePurchaseType = (type) => { + const selected = PRICE_CONFIG.find(item => item.purchaseType === type); + setAmount(type === 'bulk' ? selected.price : type === 'loose' ? selected.price : '') + setPurchaseType(type); + } + + const handlePurchase = async () => { + // Validate inputs + if (!purchaseType) { + setDataError('Please select a Plan'); + return; + } + + setIsProcessing(true); + setDataError(null); + + try { + const formData = new FormData(); + formData.append('service', 'STT Streaming API'); + formData.append('serviceId', 'sttstreamingapi'); + formData.append('cycle', 'monthly'); + formData.append('amount', amount.toString()); + formData.append('service_type', 'streaming_api'); + const response = await fetch(`${USER_API_URL}?query=initiate_payment`, { + method: 'POST', + body: formData, // Using FormData instead of JSON + credentials: 'include' + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + + if (data.success) { + // Redirect to payment success page with order ID + window.location.href = `/success?service=streaming_api&orderId=${data.order_id}`; + } else { + throw new Error(data.message || 'Payment initialization failed'); + } + } catch (error) { + console.error('Purchase error:', error); + setDataError(error.message || 'An error occurred during purchase. Please try again.'); + } finally { + setIsProcessing(false); + } + }; + if(!purchaseType){ +
+

{dataError}

+
+ } + return( + <> +
+ + + + STT Streaming API + Real-time Speech-to-Text (STT) streaming that converts spoken words into accurate, readable text + +
+ + +
+
    + {['Setup Charge 5000', '10000 Min INR 2000 in Loose Plan', '10000 Min INR 1000 in Bulk Plan', 'Real-time transcription with high accuracy', 'Supports multiple languages', 'Custom vocabulary for domain-specific terms', 'Integrates easily with video/audio streams', 'Secure and scalable API access', 'Live subtitle overlay options'].map((feature, index) => ( +
  • + + + + {feature} +
  • + ))} +
+
+ +
+
+
+
+ + ) +} \ No newline at end of file diff --git a/src/components/ContactForm.tsx b/src/components/ContactForm.jsx similarity index 79% rename from src/components/ContactForm.tsx rename to src/components/ContactForm.jsx index 820acb6..b3963d3 100644 --- a/src/components/ContactForm.tsx +++ b/src/components/ContactForm.jsx @@ -4,53 +4,57 @@ import { Textarea } from './ui/textarea'; import { Label } from './ui/label'; import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "./ui/select"; import { Button } from './ui/button'; - export function ContactForm() { - const [formState, setFormState] = useState({ - name: '', - email: '', - company: '', - service: '', - message: '', - }); + const [formState, setFormState] = useState({ name: '', email: '', company: '', service: '', message: '' }); + const [formStatus, setFormStatus] = useState('idle'); + const USER_API_URL = 'https://host-api.cs1.hz.siliconpin.com/v1/users/'; - const [formStatus, setFormStatus] = useState<'idle' | 'submitting' | 'success' | 'error'>('idle'); - - const handleInputChange = (e: React.ChangeEvent) => { + const handleInputChange = (e) => { const { name, value } = e.target; setFormState(prev => ({ ...prev, [name]: value })); }; - const handleSelectChange = (value: string) => { + const handleSelectChange = (value) => { setFormState(prev => ({ ...prev, service: value })); - console.log(formState) + // console.log(formState) }; - const handleSubmit = async (e: React.FormEvent) => { + const handleSubmit = async (e) => { e.preventDefault(); setFormStatus('submitting'); try { - // Simulate API call - await new Promise(resolve => setTimeout(resolve, 1500)); - - console.log('Form submitted:', formState); - setFormStatus('success'); + const payload = { + name: formState.name, + email: formState.email, + company: formState.company, + service_intrest: formState.service, + message: formState.message + }; - // Reset form - setFormState({ - name: '', - email: '', - company: '', - service: '', - message: '', - }); + const response = await fetch(`${USER_API_URL}?query=contact-form`, { + method: "POST", + credentials: "include", + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(payload) + }); - setTimeout(() => setFormStatus('idle'), 3000); + const data = await response.json(); + // console.log('Form Response', data); + + if(data.success) { + setFormStatus('success'); + // Reset form only after successful submission + setFormState({ name: '', email: '', company: '', service: '', message: '' }); + } else { + setFormStatus('error'); + console.error('Backend error:', data.message); + } } catch (error) { - console.error('Submission error:', error); - setFormStatus('error'); - setTimeout(() => setFormStatus('idle'), 3000); + console.error('Submission error:', error); + setFormStatus('error'); } }; diff --git a/src/components/Login.tsx b/src/components/Login.tsx index ddeab55..f442d98 100644 --- a/src/components/Login.tsx +++ b/src/components/Login.tsx @@ -123,6 +123,13 @@ const LoginPage = () => { } }; + // Set Coockie Function + function setCookie(name : string, value : string, daysToExpire : number) { + const date = new Date(); + date.setTime(date.getTime() + (daysToExpire * 24 * 60 * 60 * 1000)); + const expires = "expires=" + date.toUTCString(); + document.cookie = `${name}=${value}; ${expires}; path=/`; + } const handleCreateUserInMongo = async (siliconId: string) => { try { const response = await fetch(`https://hostapi2.cs1.hz.siliconpin.com/api/users`, { @@ -184,7 +191,7 @@ const LoginPage = () => { // Step 3: Redirect to profile if all are ok window.location.href = '/profile'; - + setCookie('token', data.userData.accessToken, 7); return data; } catch (error: any) { console.error('Sync Error:', error); diff --git a/src/components/NewTopic copy.jsx b/src/components/NewTopic copy.jsx new file mode 100644 index 0000000..25bfecb --- /dev/null +++ b/src/components/NewTopic copy.jsx @@ -0,0 +1,485 @@ +import React, { useState, useEffect, useRef } from "react"; +import MDEditor, { commands } from '@uiw/react-md-editor'; +import { Input } from './ui/input'; +import { Label } from './ui/label'; +import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from './ui/select'; +import { Button } from './ui/button'; +import { Separator } from './ui/separator'; +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from './ui/dialog'; +import { CustomTabs } from './ui/tabs'; + +const TOPIC_API_URL = 'https://host-api.cs1.hz.siliconpin.com/v1/topics/'; +const MINIO_UPLOAD_URL = 'https://hostapi2.cs1.hz.siliconpin.com/api/storage/upload'; + +const NewTopic = () => { + + // Form state + const [formData, setFormData] = useState({ status: 'draft', category: '', title: '', content: '', imageUrl: '' }); + // UI state + const [isSubmitting, setIsSubmitting] = useState(false); + const [error, setError] = useState(null); + const [success, setSuccess] = useState(false); + const [imageFile, setImageFile] = useState(null); + const [uploadProgress, setUploadProgress] = useState(0); + const [imageDialogOpen, setImageDialogOpen] = useState(false); + const [imageUrlInput, setImageUrlInput] = useState(''); + const [imageUploadFile, setImageUploadFile] = useState(null); + const [imageUploadPreview, setImageUploadPreview] = useState(''); + const [editorMode, setEditorMode] = useState('edit'); + + // Upload file to MinIO + const uploadToMinIO = async (file, onProgress) => { + const formData = new FormData(); + formData.append('file', file); + formData.append('api_key', 'wweifwehfwfhwhtuyegbvijvbfvegfreyf'); + + try { + const response = await fetch(MINIO_UPLOAD_URL, { + method: 'POST', + body: formData, + credentials: 'include', + }); + + if (!response.ok) { + throw new Error('Upload failed'); + } + + const data = await response.json(); + console.log(data) + return data.url; + } catch (error) { + console.error('Upload error:', error); + throw error; + } + }; + + // // Generate slug from title + // useEffect(() => { + // if (formData.title) { + // const slug = formData.title + // .toLowerCase() + // .replace(/[^\w\s]/g, '') + // .replace(/\s+/g, '-'); + // setFormData(prev => ({ ...prev, slug })); + // } + // }, [formData.title]); + + const customImageCommand = { + name: 'image', + keyCommand: 'image', + buttonProps: { 'aria-label': 'Insert image' }, + icon: ( + + + + ), + execute: () => { + setImageDialogOpen(true); + }, + }; + + // Get all default commands and replace the image command + const allCommands = commands.getCommands().map(cmd => { + if (cmd.name === 'image') { + return customImageCommand; + } + return cmd; + }); + + + // Handle image URL insertion + const handleInsertImageUrl = () => { + if (imageUrlInput) { + const imgMarkdown = `![Image](${imageUrlInput})`; + const textarea = document.querySelector('.w-md-editor-text-input'); + if (textarea) { + const startPos = textarea.selectionStart; + const endPos = textarea.selectionEnd; + const currentValue = formData.content; + + const newValue = + currentValue.substring(0, startPos) + + imgMarkdown + + currentValue.substring(endPos); + + setFormData(prev => ({ ...prev, content: newValue })); + } + setImageDialogOpen(false); + setImageUrlInput(''); + } + }; + + // Handle image file selection + const handleImageFileSelect = (e) => { + const file = e.target.files[0]; + if (file) { + setImageUploadFile(file); + + // Create preview + const reader = new FileReader(); + reader.onload = () => { + setImageUploadPreview(reader.result); + }; + reader.readAsDataURL(file); + } + }; + + // Upload image file to MinIO and insert into editor + const handleImageUpload = async () => { + if (!imageUploadFile) return; + + try { + setIsSubmitting(true); + setUploadProgress(0); + + const uploadedUrl = await uploadToMinIO(imageUploadFile, (progress) => { + setUploadProgress(progress); + }); + + // Insert markdown for the uploaded image + const imgMarkdown = `![Image](${uploadedUrl})`; + const textarea = document.querySelector('.w-md-editor-text-input'); + if (textarea) { + const startPos = textarea.selectionStart; + const endPos = textarea.selectionEnd; + const currentValue = formData.content; + + const newValue = + currentValue.substring(0, startPos) + + imgMarkdown + + currentValue.substring(endPos); + + setFormData(prev => ({ ...prev, content: newValue })); + } + + setImageDialogOpen(false); + setImageUploadFile(null); + setImageUploadPreview(''); + } catch (error) { + setError('Failed to upload image: ' + error.message); + } finally { + setIsSubmitting(false); + } + }; + + // Form submission + const handleSubmit = async (e) => { + e.preventDefault(); + setIsSubmitting(true); + setError(null); + setUploadProgress(0); + + try { + // Upload featured image if selected + let imageUrl = formData.imageUrl; + if (imageFile) { + imageUrl = await uploadToMinIO(imageFile, (progress) => { + setUploadProgress(progress); + }); + } + + // Prepare payload + const payload = { + ...formData, + imageUrl + }; + + // Submit to API + const response = await fetch(`${TOPIC_API_URL}?query=create-new-topic`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + credentials: 'include', + body: JSON.stringify(payload) + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.message || 'Failed to create topic'); + } + + setSuccess(true); + } catch (err) { + setError(err.message); + } finally { + setIsSubmitting(false); + setUploadProgress(0); + } + }; + + // Handle form field changes + const handleChange = (e) => { + const { name, value } = e.target; + setFormData(prev => ({ ...prev, [name]: value })); + }; + + // Handle featured image file selection + const handleFileChange = (e) => { + const file = e.target.files[0]; + if (file) { + setImageFile(file); + // Preview image + const reader = new FileReader(); + reader.onload = () => { + setFormData(prev => ({ ...prev, imageUrl: reader.result })); + }; + reader.readAsDataURL(file); + } + }; + + // Reset form + const resetForm = () => { + setFormData({ + status: 'draft', + category: '', + title: '', + slug: '', + content: '', + imageUrl: '' + }); + setImageFile(null); + setSuccess(false); + setError(null); + }; + + // Success state + if (success) { + return ( +
+

Topic created successfully!

+
+ + +
+
+ ); + } + + return ( +
+
+

Create New Topic

+

Start a new discussion in the SiliconPin community

+ +
+
+
+ + +
+ +
+ + +
+
+ + {/* Title and Slug */} +
+ + +
+ + {/*
+ + +

This will be used in the topic URL

+
*/} + + {/* Content Editor with Preview Toggle */} +
+
+ + +
+
+ setFormData(prev => ({ ...prev, content: value || '' }))} + height={400} + preview={editorMode} + commands={allCommands} + /> +
+
+ + {/* Image Upload Dialog */} + + + + Insert Image + + + setImageUrlInput(e.target.value)} + /> +
+ +
+
+ ) + }, + { + label: "Upload", + value: "upload", + content: ( +
+ + {imageUploadPreview && ( +
+ Preview +
+ )} + {uploadProgress > 0 && uploadProgress < 100 && ( +
+
+
+ )} +
+ +
+
+ ) + } + ]} + /> + + + + {/* Featured Image Upload */} +
+ + + + {uploadProgress > 0 && uploadProgress < 100 && ( +
+
+
+ )} + + {formData.imageUrl && ( +
+ Preview +
+ )} +
+ + + + {/* Form Actions */} +
+ + +
+ + {error && ( +
+ Error: {error} +
+ )} + +
+ + ); +}; + +export default NewTopic; \ No newline at end of file diff --git a/src/components/NewTopic.jsx b/src/components/NewTopic.jsx index cc26557..c994a1e 100644 --- a/src/components/NewTopic.jsx +++ b/src/components/NewTopic.jsx @@ -9,7 +9,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from import { CustomTabs } from './ui/tabs'; const TOPIC_API_URL = 'https://host-api.cs1.hz.siliconpin.com/v1/topics/'; -const MINIO_UPLOAD_URL = 'https://your-minio-api-endpoint/upload'; +const MINIO_UPLOAD_URL = 'https://hostapi2.cs1.hz.siliconpin.com/api/storage/upload'; const NewTopic = () => { @@ -31,14 +31,13 @@ const NewTopic = () => { const uploadToMinIO = async (file, onProgress) => { const formData = new FormData(); formData.append('file', file); - formData.append('bucket', 'siliconpin-uploads'); - formData.append('folder', 'topic-images'); + formData.append('api_key', 'wweifwehfwfhwhtuyegbvijvbfvegfreyf'); try { const response = await fetch(MINIO_UPLOAD_URL, { method: 'POST', body: formData, - credentials: 'include', + credentials: 'include' }); if (!response.ok) { @@ -46,7 +45,8 @@ const NewTopic = () => { } const data = await response.json(); - return data.url; + console.log(data.publicUrl) + return data.publicUrl; } catch (error) { console.error('Upload error:', error); throw error; @@ -127,7 +127,7 @@ const NewTopic = () => { // Upload image file to MinIO and insert into editor const handleImageUpload = async () => { if (!imageUploadFile) return; - + console.log(imageUploadFile) try { setIsSubmitting(true); setUploadProgress(0); @@ -174,10 +174,11 @@ const NewTopic = () => { let imageUrl = formData.imageUrl; if (imageFile) { imageUrl = await uploadToMinIO(imageFile, (progress) => { + console.log('imageUrl', imageUrl) setUploadProgress(progress); }); } - + // let finalImageUrl = imageUrl.publicUrl; // Prepare payload const payload = { ...formData, diff --git a/src/components/PaymentSuccessfully.jsx b/src/components/PaymentSuccessfully.jsx index 15dcf34..f4a1f79 100644 --- a/src/components/PaymentSuccessfully.jsx +++ b/src/components/PaymentSuccessfully.jsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './ui/card'; import { Button } from './ui/button'; import { FileDown } from "lucide-react"; import { useIsLoggedIn } from '../lib/isLoggedIn'; @@ -32,7 +33,7 @@ export default function HestiaCredentialsFetcher() { }, [sessionData]); const handleSaveDataInMongoDB = async (servicesData, currentBillingId, serviceToEndpoint, siliconId) => { - const query = serviceToEndpoint === 'vpn' ? 'vpns' : serviceToEndpoint === 'hosting' ? hostings : ''; + const query = serviceToEndpoint === 'vpn' ? 'vpns' : serviceToEndpoint === 'hosting' ? 'hostings' : ''; try { const serviceDataPayload = { success: servicesData.success, @@ -46,7 +47,7 @@ export default function HestiaCredentialsFetcher() { billingId: currentBillingId, status: "active" } - console.log('serviceDataPayload', serviceDataPayload) + // console.log('serviceDataPayload', serviceDataPayload) const response = await fetch(`https://hostapi2.cs1.hz.siliconpin.com/api/users/${siliconId}/${query}`, { method: 'POST', headers: { @@ -108,7 +109,7 @@ export default function HestiaCredentialsFetcher() { element.click(); document.body.removeChild(element); }; - +console.log('serviceName', serviceName) if (loading) { return ; } @@ -168,7 +169,7 @@ export default function HestiaCredentialsFetcher() { {error &&

{error}

} - ) : creds && creds.service === 'hestia' && ( + ) : creds && creds.service === 'hestia' ? (

Hestia Credentials

@@ -186,7 +187,16 @@ export default function HestiaCredentialsFetcher() { {error &&

{error}

}
- )} + ) : serviceName === 'streaming_api' ? ( + + + + STT Streaming API Purchase Succesfully + You can See Info on my Billing Section in Profile + + + + ) : ''} ); } diff --git a/src/components/ServiceCard.tsx b/src/components/ServiceCard.tsx index be75ec9..13c0b61 100644 --- a/src/components/ServiceCard.tsx +++ b/src/components/ServiceCard.tsx @@ -2,7 +2,6 @@ import React, { useState } from 'react'; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './ui/card'; import { Button } from './ui/button'; import { useIsLoggedIn } from '../lib/isLoggedIn'; -import Loader from "./ui/loader"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "./ui/dialog"; export interface ServiceCardProps { @@ -25,6 +24,7 @@ export function ServiceCard({ title, description, imageUrl, features, learnMoreU return; } window.location.href = buyButtonUrl; + console.log(buyButtonUrl) }; return ( @@ -39,7 +39,7 @@ export function ServiceCard({ title, description, imageUrl, features, learnMoreU {title} - {description} + {description}
    @@ -60,7 +60,7 @@ export function ServiceCard({ title, description, imageUrl, features, learnMoreU href={learnMoreUrl} className="inline-flex items-center justify-center rounded-md bg-[#6d9e37] px-4 py-2 text-sm font-medium text-white hover:bg-[#598035] transition-colors w-full" > - Learn More + Details diff --git a/src/components/TopicItem.jsx b/src/components/TopicItem.jsx index 7049c80..90cdaf9 100644 --- a/src/components/TopicItem.jsx +++ b/src/components/TopicItem.jsx @@ -6,7 +6,7 @@ import { useIsLoggedIn } from '../lib/isLoggedIn'; import { Pencil, Trash2, Search } from "lucide-react"; import { marked } from 'marked'; export default function TopicItems(props) { - console.table(props.topics) + // console.table(props.topics) const { isLoggedIn, loading, error, sessionData } = useIsLoggedIn(); const [localSearchTerm, setLocalSearchTerm] = React.useState(props.searchTerm || ''); diff --git a/src/components/UserProfile.tsx b/src/components/UserProfile.tsx index 55c97d1..a87edf7 100644 --- a/src/components/UserProfile.tsx +++ b/src/components/UserProfile.tsx @@ -4,7 +4,6 @@ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, D import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "./ui/card"; import { Input } from "./ui/input"; import { Label } from "./ui/label"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from "./ui/select"; import { Separator } from "./ui/separator"; import { Textarea } from "./ui/textarea"; import React, { useState, useEffect } from 'react'; @@ -266,7 +265,42 @@ export default function ProfilePage() {
    - + + +
    + My Services + {/* View All */} +
    + + + View your all Services. + + + + + + + + + {/* */} + + + + { + invoiceList.slice(0, 5).map((invoice, index) => ( + + + + + + + )) + } + +
    Order IDDateDescriptionStatusAction
    {invoice.billing_id}{invoice?.created_at.split(' ')[0]}

    {invoice.service}

    {invoice.service_status === '1' ? 'Active' : invoice.service_status === '0' ? 'Unactive' : ''}
    +
    +
    + Danger Zone diff --git a/src/pages/contact.astro b/src/pages/contact.astro index e91f29b..2ab190d 100644 --- a/src/pages/contact.astro +++ b/src/pages/contact.astro @@ -62,7 +62,7 @@ const contactSchema = {
    -
    +

    Send us a message

    diff --git a/src/pages/services/index.astro b/src/pages/services/index.astro index bc007d2..84f5a81 100644 --- a/src/pages/services/index.astro +++ b/src/pages/services/index.astro @@ -1,6 +1,6 @@ --- import Layout from '../../layouts/Layout.astro'; -import { ServiceCard } from '../../components/ServiceCard'; +import {ServiceCard} from '../../components/ServiceCard'; // Page-specific SEO metadata const pageTitle = "Hosting Services | SiliconPin"; @@ -12,7 +12,7 @@ const services = [ { title: 'VPN (WireGuard)', description: 'WireGuard is much better than other solutions like open VPN Free VPN. as WireGuard is the best we provide WireGuard VPN', - imageUrl: '/assets/images/wiregurd-thumb.jpg', + imageUrl: '/assets/images/services/wiregurd-thumb.jpg', features: ["600 GB bandwidth", "WireGuard® protocol", "Global server locations", "No activity logs"], learnMoreUrl: '/services/vpn', buyButtonText: 'Buy VPN', @@ -20,7 +20,7 @@ const services = [ },{ title: 'Deploy an App', description: 'WordPress, Joomla, Drupal, PrestaShop, Wiki, Moodle, Directus, PocketBase, StarAPI and more.', - imageUrl: '/assets/images/deployapp-thumb.jpg', + imageUrl: '/assets/images/services/deployapp-thumb.jpg', features: [ 'WordPress', 'Joomla', 'Drupal', 'PrestaShop', 'Wiki', 'Moodle', 'Directus', 'PocketBase', 'StarAPI' ], learnMoreUrl: '/services/deploy-an-app', buyButtonText: '', @@ -56,16 +56,25 @@ const services = [ { title: "Node.js Hosting", description: "Optimized cloud hosting for Node.js applications with automatic scaling.", - imageUrl: "/assets/node-js.jpg", + imageUrl: "/assets/images/services/node-js.jpg", features: ["Express", "NestJS", "Koa", "Socket.io", "PM2", "WebSockets", "Serverless", "TypeScript", "GraphQL"], learnMoreUrl: "/services/nodejs-hosting", buyButtonText: "", buyButtonUrl: "" }, + { + title: 'STT Streaming (API Services)', + description: 'Real-time Speech-to-Text (STT) streaming that converts spoken words into accurate, readable text. Ideal for live events, webinars, customer support, and accessibility solutions.', + imageUrl: '/assets/images/services/stt-streaming.png', + features: ['Setup Charge 5000', '10000 Min INR 2000 in Loose Plan', '10000 Min INR 1000 in Bulk Plan', 'Real-time transcription with high accuracy', 'Supports multiple languages', 'Custom vocabulary for domain-specific terms', 'Integrates easily with video/audio streams', 'Secure and scalable API access', 'Live subtitle overlay options'], + learnMoreUrl: '', + buyButtonText: 'Purchase', + buyButtonUrl: '/services/stt-streaming' + }, { title: 'Kubernetes (K8s)', description: 'Enterprise-grade Kubernetes clusters for container orchestration at scale.', - imageUrl: 'https://images.unsplash.com/photo-1551731409-43eb3e517a1a?q=80&w=2000&auto=format&fit=crop', + imageUrl: '/assets/images/services/kubernetes-edge.png', features: [ 'Fully managed K8s clusters', 'Auto-scaling and load balancing', 'Advanced networking options', 'Persistent storage solutions', 'Enterprise support available'], learnMoreUrl: '/services/kubernetes', buyButtonText: '', diff --git a/src/pages/services/stt-streaming.astro b/src/pages/services/stt-streaming.astro new file mode 100644 index 0000000..4a94206 --- /dev/null +++ b/src/pages/services/stt-streaming.astro @@ -0,0 +1,7 @@ +--- +import Layout from "../../layouts/Layout.astro" +import STTStreaming from "../../components/BuyServices/STTStreaming" +--- + + + \ No newline at end of file diff --git a/src/pages/tmp.astro b/src/pages/tmp.astro new file mode 100644 index 0000000..6d1b1f8 --- /dev/null +++ b/src/pages/tmp.astro @@ -0,0 +1,100 @@ +--- +import Layout from "../layouts/Layout.astro"; +--- + +
    + + +
    +
    +
    + \ No newline at end of file diff --git a/src/pages/web-tools/annyang-js.astro b/src/pages/web-tools/annyang-js.astro new file mode 100644 index 0000000..6608b29 --- /dev/null +++ b/src/pages/web-tools/annyang-js.astro @@ -0,0 +1,200 @@ +--- +import Layout from "../../layouts/Layout.astro" +--- + +
    +
    +
    +

    Real-Time Speech Transcription

    +

    Using Annyang.js for speech recognition

    +
    +
    +
    +
    +

    Transcription

    +
    + Not Listening +
    +
    +
    +

    Your transcribed text will appear here...

    +
    +
    + +
    + + + +
    + +
    + +
    +
      +
    • "clear transcript" - Clears the transcription
    • +
    • "new paragraph" - Inserts a new paragraph
    • +
    • "period", "comma", "question mark" - Adds punctuation
    • +
    +
    +
    +
    +
    +
    +
    + + \ No newline at end of file diff --git a/src/pages/web-tools/articulate.astro b/src/pages/web-tools/articulate.astro new file mode 100644 index 0000000..ec1c441 --- /dev/null +++ b/src/pages/web-tools/articulate.astro @@ -0,0 +1,168 @@ +--- +import Layout from "../../layouts/Layout.astro" +--- + + +
    +
    + +
    +

    Real-Time Transcription

    +

    Using Articulate.js

    +
    + + +
    + +
    +
    + Ready to start +
    + + +
    + +
    +

    Your transcription will appear here...

    +

    +
    +
    + + +
    + + + + + + +
    +
    + + +
    +

    Click "Start" and begin speaking. Transcription will appear in real-time.

    +
    +
    +
    +
    + + \ No newline at end of file diff --git a/src/pages/web-tools/deep-speech.astro b/src/pages/web-tools/deep-speech.astro new file mode 100644 index 0000000..c2af2eb --- /dev/null +++ b/src/pages/web-tools/deep-speech.astro @@ -0,0 +1,73 @@ +--- +import Layout from "../../layouts/Layout.astro"; +--- + +

    DeepSpeech Real-Time Transcription

    + + +
    +
    + \ No newline at end of file diff --git a/src/pages/web-tools/transcribe.astro b/src/pages/web-tools/transcribe.astro new file mode 100644 index 0000000..4cbeb3b --- /dev/null +++ b/src/pages/web-tools/transcribe.astro @@ -0,0 +1,70 @@ +--- +import Layout from "../../layouts/Layout.astro" +--- + +
    +

    Voice Recognition Demo

    + + +
    +
    +
    + diff --git a/src/pages/web-tools/vosk.astro b/src/pages/web-tools/vosk.astro new file mode 100644 index 0000000..8f02ad7 --- /dev/null +++ b/src/pages/web-tools/vosk.astro @@ -0,0 +1,248 @@ +--- +import Layout from "../../layouts/Layout.astro" +--- + +
    +
    +

    🎙️ Speech to Text

    + +
    + +
    + + + +
    + + +
    + Ready to start +
    + + +
    + Transcribed text will appear here... +
    +
    +
    +
    +
    + diff --git a/src/pages/web-tools/web-speech.astro b/src/pages/web-tools/web-speech.astro new file mode 100644 index 0000000..4adde88 --- /dev/null +++ b/src/pages/web-tools/web-speech.astro @@ -0,0 +1,100 @@ +--- +import Layout from "../../layouts/Layout.astro"; +--- + +
    + + +
    +
    +
    + \ No newline at end of file diff --git a/src/pages/web-tools/whisper-cpp.astro b/src/pages/web-tools/whisper-cpp.astro new file mode 100644 index 0000000..0a78a1e --- /dev/null +++ b/src/pages/web-tools/whisper-cpp.astro @@ -0,0 +1,276 @@ +--- +import Layout from "../../layouts/Layout.astro" +--- + +
    +
    +
    +

    Whisper.cpp STT Streaming

    + +
    +
    + + + +
    + +
    + + +
    + +
    + + +
    +
    + +
    + +
    + Ready to start recording... +
    +
    + +
    + +
    + +
    +
    + +
    +

    Note: This interface connects to a whisper.cpp server for processing. Audio is streamed in real-time.

    +
    +
    +
    +
    +
    + \ No newline at end of file