Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
.DS_Store
*.pem

# lint cache
.cache

# debug
npm-debug.log*
yarn-debug.log*
Expand Down
17 changes: 12 additions & 5 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,19 @@ const compat = new FlatCompat({

export default [
stylistic.configs.recommended,
nextPlugin.configs.recommended,
...fixupConfigRules(compat.extends(
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-type-checked',
'plugin:import/warnings',
'plugin:import/typescript',
'plugin:@next/next/recommended'
'plugin:import/typescript'
)), {
plugins: {
'@typescript-eslint': fixupPluginRules(typescriptEslint),
'perfectionist': perfectionist,
'import': fixupPluginRules(_import),
'yenz': fixupPluginRules(yenz),
'@next/next': fixupPluginRules(nextPlugin)
'yenz': fixupPluginRules(yenz)
},

languageOptions: {
Expand All @@ -48,6 +47,8 @@ export default [
'perfectionist/sort-switch-case': 'off',
'@stylistic/comma-dangle': 'off',
'@stylistic/indent': 'off',
// Its autofix drops whitespace between inline text and elements.
'@stylistic/jsx-one-expression-per-line': 'off',
'@stylistic/no-multiple-empty-lines': 'off',
'@stylistic/no-trailing-spaces': ['error'],
'@typescript-eslint/explicit-function-return-type': ['error', {
Expand Down Expand Up @@ -141,6 +142,12 @@ export default [
}
},
{
ignores: ['src/components/ui/**'],
ignores: [
'.next/**',
'out/**',
'build/**',
'next-env.d.ts',
'src/components/ui/**'
],
}
]
7 changes: 4 additions & 3 deletions next.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { NextConfig } from "next";
import type { NextConfig } from 'next'


const nextConfig: NextConfig = {
/* config options here */
};
}

export default nextConfig;
export default nextConfig
38 changes: 19 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
{
"name": "void-works",
"version": "0.6.0",
"version": "0.7.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "eslint . --cache --cache-location .cache/eslint"
},
"dependencies": {
"@radix-ui/react-slot": "^1.2.3",
"@vercel/analytics": "1.5.0",
"@vercel/analytics": "2.0.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.511.0",
"lucide-react": "1.46.0",
"next": "^16.2.9",
"next-themes": "^0.4.6",
"react": "19.0.0",
"react-dom": "19.0.0",
"react": "19.3.0",
"react-dom": "19.3.0",
"tailwind-merge": "^3.6.0"
},
"devDependencies": {
"@eslint/compat": "1.2.9",
"@eslint/eslintrc": "3.3.5",
"@eslint/compat": "2.1.1",
"@eslint/eslintrc": "3.3.7",
"@eslint/js": "10.0.1",
"@next/eslint-plugin-next": "^16.1.2",
"@stylistic/eslint-plugin": "4.4.0",
"@stylistic/eslint-plugin": "5.10.0",
"@tailwindcss/postcss": "^4",
"@types/jest": "^30.0.0",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"@typescript-eslint/eslint-plugin": "8.33.0",
"@typescript-eslint/parser": "8.33.0",
"eslint": "^9",
"@types/node": "22.20.3",
"@types/react": "19.3.0",
"@types/react-dom": "19.3.0",
"@typescript-eslint/eslint-plugin": "8.70.0",
"@typescript-eslint/parser": "8.70.0",
"eslint": "10.10.0",
"eslint-config-next": "^16.1.2",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-jest": "29.15.2",
"eslint-plugin-perfectionist": "4.13.0",
"eslint-plugin-yenz": "1.2.0",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-jest": "29.16.6",
"eslint-plugin-perfectionist": "5.11.1",
"eslint-plugin-yenz": "2.2.2",
"tailwindcss": "^4",
"tw-animate-css": "^1.3.2",
"typescript": "^5"
Expand Down
6 changes: 3 additions & 3 deletions postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const config = {
plugins: ["@tailwindcss/postcss"],
};
plugins: ['@tailwindcss/postcss'],
}

export default config;
export default config
1 change: 1 addition & 0 deletions src/app/.well-known/[...path]/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NextRequest, NextResponse } from 'next/server'


export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ path: string[] }> },
Expand Down
38 changes: 30 additions & 8 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
--font-sans: var(--font-instrument-sans), system-ui, sans-serif;
--font-mono: var(--font-ibm-plex-mono), ui-monospace, monospace;
--color-brand: var(--brand);
--color-brand-solid: var(--brand-solid);
--color-brand-solid-hover: var(--brand-solid-hover);
--color-brand-soft: var(--brand-soft);
--color-brand-softer: var(--brand-softer);
--color-body-muted: var(--body-muted);
--color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
Expand Down Expand Up @@ -45,24 +51,31 @@

:root {
--radius: 0.625rem;
--background: oklch(0 0 0);
--foreground: oklch(1 0 0);
--card: oklch(0.15 0 0);
--card-foreground: oklch(1 0 0);
--background: #08080a;
--foreground: #f4f4f6;
--card: #101013;
--card-foreground: #f4f4f6;
--popover: oklch(0.15 0 0);
--popover-foreground: oklch(1 0 0);
--primary: oklch(0.929 0.013 255.508);
--primary-foreground: oklch(0 0 0);
--secondary: oklch(0.279 0.041 260.031);
--secondary-foreground: oklch(1 0 0);
--muted: oklch(0.279 0.041 260.031);
--muted-foreground: oklch(0.704 0.04 256.788);
--muted-foreground: #9a9aa2;
--accent: oklch(0.279 0.041 260.031);
--accent-foreground: oklch(1 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--border: rgb(255 255 255 / 8%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.551 0.027 264.364);
--brand: #5b6cf0;
/* Deeper indigo for white-text surfaces: meets 4.5:1 contrast (base ~5.3:1, hover ~4.7:1) */
--brand-solid: #4c5ce6;
--brand-solid-hover: #5566eb;
--brand-soft: #8e9bff;
--brand-softer: #b4bdff;
--body-muted: #a8a8b0;
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
Expand Down Expand Up @@ -119,4 +132,13 @@
body {
@apply bg-background text-foreground;
}
::selection {
background: var(--brand-solid);
color: #ffffff;
}
@media (prefers-reduced-motion: no-preference) {
html {
scroll-behavior: smooth;
}
}
}
19 changes: 8 additions & 11 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
import { Analytics } from '@vercel/analytics/next'
import type { Metadata } from 'next'
import { Geist, Geist_Mono } from 'next/font/google'
import { IBM_Plex_Mono, Instrument_Sans } from 'next/font/google'

import { Widget as ProductlaneWidget } from '@/components/productlane/widget'

import './globals.css'


const geistSans = Geist({
variable: '--font-geist-sans',
const instrumentSans = Instrument_Sans({
variable: '--font-instrument-sans',
subsets: ['latin'],
})

const geistMono = Geist_Mono({
variable: '--font-geist-mono',
const ibmPlexMono = IBM_Plex_Mono({
variable: '--font-ibm-plex-mono',
subsets: ['latin'],
weight: ['400', '500'],
})

export const metadata: Metadata = {
title: 'Void Works',
description: 'Developer tools for the modern era',
}

function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>): React.ReactNode {
function RootLayout({ children }: Readonly<{ children: React.ReactNode }>): React.ReactNode {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
className={`${instrumentSans.variable} ${ibmPlexMono.variable} font-sans antialiased`}
>
{children}
<ProductlaneWidget />
Expand Down
79 changes: 16 additions & 63 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import type { Metadata } from 'next'
import Image from 'next/image'

import { AnimatedProductSection } from '@/components/animated-product-section'
import { FixedFooterLinks } from '@/components/fixed-footer-links'
import { Footer } from '@/components/footer'
import { ScrollIndicator } from '@/components/scroll-indicator'
import { Button } from '@/components/ui/button'
import { Header } from '@/components/header'
import { Hero } from '@/components/hero'
import { ProjectsSection } from '@/components/projects-section'


const APP_NAME = 'Void Works'
const APP_DESCRIPTION = 'Creating innovative solutions across platforms and technologies'
const DEFAULT_URL = 'https://voidworks.io'

// Regenerate daily so the footer's copyright year stays current.
export const revalidate = 86400

export const metadata: Metadata = {
title: APP_NAME,
description: APP_DESCRIPTION,
Expand Down Expand Up @@ -103,20 +104,6 @@ export default function Home(): React.ReactNode {
}

const productSchemas = [
{
'@context': 'https://schema.org',
'@type': 'SoftwareApplication',
'name': 'Shortcut Assistant',
'applicationCategory': 'BrowserApplication',
'operatingSystem': 'Chrome',
'description': 'Enhance your browsing experience with powerful keyboard shortcuts and productivity tools.',
'url': 'https://chromewebstore.google.com/detail/shortcut-assistant/kmdlofehocppnlkpokdbiaalcelhedef',
'offers': {
'@type': 'Offer',
'price': '0',
'priceCurrency': 'USD',
},
},
{
'@context': 'https://schema.org',
'@type': 'MobileApplication',
Expand All @@ -142,7 +129,7 @@ export default function Home(): React.ReactNode {
]

return (
<main className="min-h-screen bg-black">
<div className="min-h-screen text-base">
{/* Structured Data */}
<script
type="application/ld+json"
Expand All @@ -160,48 +147,14 @@ export default function Home(): React.ReactNode {
/>
))}

{/* Hero Section with Background */}
<section className="relative min-h-screen flex items-center justify-center overflow-hidden">
<div className="absolute inset-0 z-0">
<div className="absolute inset-0 bg-gradient-to-b from-black/60 via-black/40 to-black z-10" />
<Image
src="/images/hero-background.jpg"
alt="Abstract technology background with modern design elements"
className="w-full h-full object-cover"
width={1920}
height={1080}
priority
/>
</div>

<div className="container mx-auto px-4 py-24 relative z-20">
<div className="max-w-5xl space-y-8">
<h1 className="text-5xl md:text-7xl lg:text-8xl font-bold tracking-tight text-white leading-[1.1] text-balance">
Solutions that matter, designed thoughtfully.
</h1>
<p className="text-lg md:text-xl text-white/80 max-w-2xl leading-relaxed">
Building innovative solutions across platforms and technologies. From browser extensions to mobile apps and web
applications, we create tools that solve real-world problems.
</p>
<div className="flex gap-4 pt-4">
<Button asChild size="lg" className="bg-white text-black hover:bg-white/90">
<a href="mailto:hello@voidworks.io">Get in touch</a>
</Button>
</div>
</div>
</div>

{/* Scroll Indicator */}
<ScrollIndicator />
</section>

{/* Products Section */}
<section id="products" className="container mx-auto px-4 py-24 relative z-10">
<AnimatedProductSection />
</section>

<Footer />
<FixedFooterLinks />
</main>
<div className="mx-auto max-w-[1080px] px-8">
<Header />
<main>
<Hero />
<ProjectsSection />
</main>
<Footer />
</div>
</div>
)
}
15 changes: 0 additions & 15 deletions src/components/animated-product-section.tsx

This file was deleted.

Loading