Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d71fedb
Initial plan
Copilot Aug 24, 2025
285dafd
Initial setup: temporarily remove cypress dependencies for development
Copilot Aug 24, 2025
f09d0d7
Enhance error.tsx with comprehensive error handling and user reporting
Copilot Aug 24, 2025
7c7fb73
Complete enhanced error handling implementation with documentation
Copilot Aug 24, 2025
1a46f79
update cypress and avoid fanky crafts issue
Ekwav Aug 24, 2025
412078e
patch report format
Ekwav Aug 24, 2025
fdc2b0b
Revert "Initial setup: temporarily remove cypress dependencies for de…
Ekwav Aug 24, 2025
21a9803
clear up ai slop
Ekwav Aug 24, 2025
8166009
implement bazaar flips
matthias-luger Aug 19, 2025
584fdf5
bazaar flips and generic flip page
matthias-luger Aug 22, 2025
67ec401
Add bazaar flip explanations
Ekwav Aug 23, 2025
e99d187
update sorting
Ekwav Aug 23, 2025
138adb4
improve performance
matthias-luger Aug 31, 2025
ab80fe6
fix rerenders
matthias-luger Aug 31, 2025
45cb093
update bazaar link
matthias-luger Aug 31, 2025
f761758
Add attribute and ananke flips
Ekwav Aug 26, 2025
d932389
correct filter example
Ekwav Aug 29, 2025
5bb7733
Update utils/QueryUtils.tsx
matthias-luger Aug 31, 2025
5f993e4
Update components/CraftsList/CraftsList.tsx
matthias-luger Aug 31, 2025
9bdbc9a
Update components/BazaarFlips/BazaarFlips.tsx
matthias-luger Aug 31, 2025
db9d845
Update components/BazaarFlips/BazaarFlips.tsx
matthias-luger Aug 31, 2025
da5feb6
Update components/BazaarFlips/BazaarFlips.tsx
matthias-luger Aug 31, 2025
3959adf
- remove accountInfo
matthias-luger Aug 31, 2025
83501a3
fix SSR
matthias-luger Sep 3, 2025
49b4e66
remove link to not yet existing premium bazaar page
Ekwav Aug 31, 2025
0a50239
mention bazaar flips on no related items bazaar items
Ekwav Aug 31, 2025
37e992a
generate page descriptions
Ekwav Aug 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
jobs:
cypress-run:
timeout-minutes: 60
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion app/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,4 @@ export default async function Page() {
)
}

export const metadata = getHeadMetadata('About')
export const metadata = getHeadMetadata('About', 'Learn about Hypixel SkyBlock\'s premier auction house tracker and bazaar analyzer. Discover our features, credits, API access, and how we help millions of players optimize their trading strategies.')
2 changes: 1 addition & 1 deletion app/authmod/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ export default async function Page() {
)
}

export const metadata = getHeadMetadata('Authenticate Mod')
export const metadata = getHeadMetadata('Authenticate Mod', 'Connect your Minecraft account with our SkyCofl mod for Hypixel SkyBlock. Sync your data, enable premium features, and get real-time flipping notifications directly in-game.')
32 changes: 32 additions & 0 deletions app/bazaar/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { getHeadMetadata } from '../../utils/SSRUtils'
import NavBar from '../../components/NavBar/NavBar'
import AuthMod from '../../components/AuthMod/AuthMod'
import { Container } from 'react-bootstrap'
import { getApiFlipBazaarSpread, getGetApiFlipBazaarSpreadQueryKey, useGetApiFlipBazaarSpread } from '../../api/_generated/skyApi'
import { BazaarFlips } from '../../components/BazaarFlips/BazaarFlips'
import { getQueryClient } from '../../utils/QueryUtils'
import { dehydrate, HydrationBoundary } from '@tanstack/react-query'

export default async function Page() {
const queryClient = getQueryClient()
queryClient.prefetchQuery({
queryKey: [getGetApiFlipBazaarSpreadQueryKey()],
queryFn: () => getApiFlipBazaarSpread(),
})
return (
<>
<Container>
<h2>
<NavBar />
Bazaar Flips
</h2>
<hr />
<HydrationBoundary state={dehydrate(queryClient)}>
<BazaarFlips />
</HydrationBoundary>
</Container>
</>
)
}

export const metadata = getHeadMetadata('Bazaar Flips', 'Discover profitable Hypixel SkyBlock bazaar flipping opportunities. Real-time flip analysis, buy/sell spreads, and instant order data to maximize your coin profits.')
2 changes: 1 addition & 1 deletion app/cancel.tsx/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ export default function Page() {
)
}

export const metadata = getHeadMetadata('Payment canceled')
export const metadata = getHeadMetadata('Payment Canceled', 'Payment was canceled. No charges were made to your account. You can still access our free Hypixel SkyBlock tools or try upgrading to premium again anytime.')
2 changes: 1 addition & 1 deletion app/data/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ export default function Page() {
)
}

export const metadata = getHeadMetadata('API')
export const metadata = getHeadMetadata('API', 'Access comprehensive Hypixel SkyBlock auction and bazaar data through our free API. Get real-time prices, historical data, item information, and player statistics for your applications and tools.')
232 changes: 222 additions & 10 deletions app/error.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,233 @@
'use client'
import Link from 'next/link'
import { Button } from 'react-bootstrap'
import { Container } from 'react-bootstrap'
import { Button, Container, Alert, Form, Card, Row, Col } from 'react-bootstrap'
import { getHeadMetadata } from '../utils/SSRUtils'
import { useState, useEffect } from 'react'
import { toast } from 'react-toastify'
import api from '../api/ApiHelper'

interface ErrorReportData {
userDescription: string
includeErrorDetails: boolean
contactMethod: 'discord' | 'email' | 'none'
}

export default function Custom500({ error, reset }) {
const [showDetails, setShowDetails] = useState(false)
const [isReporting, setIsReporting] = useState(false)
const [hasReported, setHasReported] = useState(false)
const [autoReportAttempted, setAutoReportAttempted] = useState(false)
const [reportData, setReportData] = useState<ErrorReportData>({
userDescription: '',
includeErrorDetails: true,
contactMethod: 'none'
})

// Attempt automatic error reporting when component mounts
useEffect(() => {
if (!autoReportAttempted) {
setAutoReportAttempted(true)
attemptAutoReport()
}
}, [])

const attemptAutoReport = async () => {
try {
const errorReport = {
type: 'server_error',
error: error?.message || 'Unknown server error',
stack: error?.stack || 'No stack trace available',
digest: error?.digest || 'No digest available',
timestamp: new Date().toISOString(),
url: window.location.href,
userAgent: navigator.userAgent,
automaticReport: true
}

await api.sendFeedback('server_error_auto', errorReport)
console.log('Automatic error report sent successfully')
} catch (reportError) {
console.error('Failed to send automatic error report:', reportError)
// Don't show this error to the user, as it's secondary to the main error
}
}

const handleManualReport = async () => {
setIsReporting(true)
try {
const errorReport = {
otherIssue : true,
additionalInformation: JSON.stringify({
userDescription: reportData.userDescription,
type: 'server_error_manual',
error: error?.message || 'Unknown server error',
stack: reportData.includeErrorDetails ? (error?.stack || 'No stack trace available') : 'User opted not to include technical details',
digest: reportData.includeErrorDetails ? (error?.digest || 'No digest available') : 'Not included',
timestamp: new Date().toISOString(),
url: window.location.href,
userAgent: navigator.userAgent,
})
} as ReloadFeedback

await api.sendFeedback('server_error_manual', errorReport)
toast.success('Error report sent successfully! Thank you for helping us improve.')
setHasReported(true)
} catch (reportError) {
toast.error('Failed to send error report. Please try contacting us directly.')
console.error('Manual error report failed:', reportError)
} finally {
setIsReporting(false)
}
}

const errorTitle = error?.message ? `Error: ${error.message}` : 'Something went wrong'
const errorDetails = {
message: error?.message || 'Unknown error',
digest: error?.digest || 'No digest available',
timestamp: new Date().toISOString()
}

export default function Custom500({ error }) {
return (
<>
<Container>
<h1>500 - Server-side error occurred</h1>
<Link href="/" className="disableLinkStyle">
<Button>Return to main page</Button>
</Link>
<p>{JSON.stringify(error)}</p>
<Container className="mt-4">
<Row className="justify-content-center">
<Col md={8} lg={6}>
<Card>
<Card.Header className="bg-danger text-white">
<h3 className="mb-0">🚨 Oops! Something went wrong</h3>
</Card.Header>
<Card.Body>
<Alert variant="warning">
<p className="mb-2">
<strong>We're sorry!</strong> An unexpected error occurred while processing your request.
</p>
<p className="mb-0">
<small>Don't worry - we've been automatically notified and will investigate this issue.</small>
</p>
</Alert>

<div className="mb-3">
<h5>What you can do:</h5>
<ul className="mb-3">
<li>Try refreshing the page</li>
<li>Go back to the main page and try again</li>
<li>Report this error with additional details (optional)</li>
</ul>
</div>

<div className="d-grid gap-2 mb-3">
<Button variant="primary" onClick={() => window.location.reload()}>
🔄 Refresh Page
</Button>
<Link href="/" className="d-grid">
<Button variant="secondary">
🏠 Return to Main Page
</Button>
</Link>
{reset && (
<Button variant="outline-primary" onClick={reset}>
🔄 Try Again
</Button>
)}
</div>

{!hasReported && (
<Card className="mb-3">
<Card.Header>
<h6 className="mb-0">📝 Help us fix this (Optional)</h6>
</Card.Header>
<Card.Body>
<Form>
<Form.Group className="mb-3">
<Form.Label>What were you trying to do when this error occurred?</Form.Label>
<Form.Control
as="textarea"
rows={3}
value={reportData.userDescription}
onChange={(e) => setReportData({...reportData, userDescription: e.target.value})}
placeholder="Describe what you were doing when the error happened..."
/>
</Form.Group>

<Form.Group className="mb-3">
<Form.Check
type="checkbox"
label="Include technical error details (helps us debug)"
checked={reportData.includeErrorDetails}
onChange={(e) => setReportData({...reportData, includeErrorDetails: e.target.checked})}
/>
</Form.Group>

<Button
variant="success"
onClick={handleManualReport}
disabled={isReporting}
className="w-100"
>
{isReporting ? '📤 Sending...' : '📤 Send Error Report'}
</Button>
</Form>
</Card.Body>
</Card>
)}

{hasReported && (
<Alert variant="success">
<h6>✅ Thank you!</h6>
<p className="mb-0">Your error report has been sent successfully. We appreciate your help in making our service better!</p>
</Alert>
)}

<Card>
<Card.Header>
<h6 className="mb-0">💬 Need immediate help?</h6>
</Card.Header>
<Card.Body>
<p className="mb-3">If you need assistance right away, you can reach us directly:</p>
<div className="d-grid gap-2">
<a
href="https://discord.gg/wvKXfTgCfb"
target="_blank"
rel="noreferrer"
className="btn btn-primary"
>
💬 Join our Discord
</a>
<a
href="mailto:support@coflnet.com"
className="btn btn-outline-primary"
>
📧 Email Support
</a>
</div>
</Card.Body>
</Card>

<div className="mt-3 text-center">
<Button
variant="link"
size="sm"
onClick={() => setShowDetails(!showDetails)}
>
{showDetails ? '🔼 Hide' : '🔽 Show'} Technical Details
</Button>
</div>

{showDetails && (
<Alert variant="secondary" className="mt-2">
<h6>Technical Details:</h6>
<pre style={{ fontSize: '0.75rem', maxHeight: '200px', overflow: 'auto' }}>
{JSON.stringify(errorDetails, null, 2)}
</pre>
</Alert>
)}
</Card.Body>
</Card>
</Col>
</Row>
</Container>
</>
)
}

export const metadata = getHeadMetadata('Error')
export const metadata = getHeadMetadata('Error', 'An error occurred while loading the page. Please try again or contact support if the issue persists. Our Hypixel SkyBlock tools are usually available 24/7 for reliable auction and bazaar tracking.')
2 changes: 1 addition & 1 deletion app/feedback/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ export default function Page() {
)
}

export const metadata = getHeadMetadata('Feedback')
export const metadata = getHeadMetadata('Feedback', 'Share your ideas and suggestions for improving our Hypixel SkyBlock tools. Contact our support team via email or Discord to help us build better features for the community.')
2 changes: 1 addition & 1 deletion app/not-found.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ export default function NotFound() {
)
}

export const metadata = getHeadMetadata('Not found')
export const metadata = getHeadMetadata('Page Not Found', 'The page you\'re looking for doesn\'t exist. Return to our Hypixel SkyBlock auction house tracker and bazaar analyzer to continue exploring price data and trading opportunities.')
2 changes: 1 addition & 1 deletion app/premium/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ export default async function Page() {
)
}

export const metadata = getHeadMetadata('Premium', 'See available premium options to support this project')
export const metadata = getHeadMetadata('Premium', 'Upgrade to premium for advanced Hypixel SkyBlock features: priority flip notifications, enhanced bazaar analysis, exclusive tools, and priority support. Support our project while maximizing your profits.')
2 changes: 1 addition & 1 deletion app/refed/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ export default function Page() {
)
}

export const metadata = getHeadMetadata()
export const metadata = getHeadMetadata('Referral Success', 'Welcome! You\'ve been referred to the best Hypixel SkyBlock auction house and bazaar tracking tools. Start exploring profitable flips, price history, and trading opportunities.')
2 changes: 1 addition & 1 deletion app/subscriptions/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ export default function Page() {
)
}

export const metadata = getHeadMetadata('Notifiers')
export const metadata = getHeadMetadata('Notifiers', 'Set up custom price alerts and notifications for Hypixel SkyBlock items. Get notified about auction house deals, bazaar price changes, and profitable flipping opportunities via Discord or in-game.')
2 changes: 1 addition & 1 deletion app/success/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ export default function Page() {
)
}

export const metadata = getHeadMetadata('Payment successful')
export const metadata = getHeadMetadata('Payment Successful', 'Thank you for your purchase! Your premium subscription is now active. Enjoy advanced features, priority support, and enhanced Hypixel SkyBlock tools to maximize your trading profits.')
2 changes: 1 addition & 1 deletion app/trade/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ export default async function Page() {
)
}

export const metadata = getHeadMetadata('Trading')
export const metadata = getHeadMetadata('Trading', 'Create and manage Hypixel SkyBlock item trades. Connect with other players, set up wanted items, and find trading partners for efficient item exchanges in the SkyBlock community.')
2 changes: 1 addition & 1 deletion app/wiki/docs/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Selects estimated profit percentage of a flip, so how much profit you make compa
Selects the algorithm that found the flip. Allows you to blacklist certain items from one algorithm. For example you might want to have a different minprofit for the sniper finder so you could add:
```
WHITELIST
Minprofit: {{MIN_PROFIT}}*0.5
Profit: >{{MIN_PROFIT}}*0.5
FlipFinder: sniper
```
To set the minprofit to just half for all flips found by the sniper finder (lbin based flips)
Expand Down
3 changes: 3 additions & 0 deletions app/wiki/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { MDXRemote } from 'next-mdx-remote/rsc';
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import matter from 'gray-matter';
import { getHeadMetadata } from '../../utils/SSRUtils';

const docsDirectory = path.join(process.cwd(), 'app/wiki/docs');

Expand Down Expand Up @@ -40,3 +41,5 @@ export default async function Wiki() {
</article>
);
}

export const metadata = getHeadMetadata('Wiki', 'Comprehensive guides and documentation for Hypixel SkyBlock tools, trading strategies, mod features, and optimization tips. Learn how to maximize your profits and improve your gameplay.');
Loading