The official website for Viscalyx, built with Next.js 16 and deployed to Cloudflare Workers via OpenNext.
- π Multi-language support (English/Swedish) via next-intl
- π± Responsive design with Tailwind CSS 4 (mobile-first, dark mode)
- π Blog with Markdown content (remark/rehype pipeline with GFM support)
- π¨ Code syntax highlighting via Shiki with copy-to-clipboard
- π Mermaid diagram rendering (lazy-loaded, DOMPurify-sanitized)
- π Table of contents with active heading tracking
- π Reading progress indicator for blog posts
- π₯ Team member profiles
- π» Open-source contributions showcase
- π Dark/light/system theme toggle with Framer Motion animations
- πΌοΈ Image lightbox with zoom
- πͺ GDPR-compliant cookie consent with granular controls
- π Privacy-first analytics with Cloudflare Analytics Engine
- π‘οΈ Security headers (CSP, HSTS, X-Frame-Options, Permissions-Policy)
- π§ͺ Comprehensive testing with Vitest and Playwright
Our website respects user privacy and complies with GDPR cookie consent requirements:
- Cookie Consent Banner: Appears on first visit to allow users to choose their cookie preferences
- Granular Control: Users can accept/reject different categories of cookies:
- Strictly Necessary: Required for website functionality (always enabled)
- Preferences: Remember user settings like theme and language preferences
- Analytics: Track website usage through Cloudflare Analytics Engine
- Privacy-First Analytics: We collect minimal data for website improvement:
- Reading progress and time spent on blog posts
- Geographic location (country-level) via Cloudflare
- Referrer information and basic browser data
- No client-side tracking cookies β all processing happens server-side
- User Rights: Users can change preferences, export data, or reset consent at any time
- β Explicit Consent: Clear opt-in required for non-essential cookies
- β Granular Choice: Users can select specific cookie categories
- β Easy Withdrawal: Users can change preferences anytime
- β Clear Information: Detailed cookie descriptions provided
- β Record Keeping: Consent timestamp and settings stored
- β No Pre-checked Boxes: All non-essential cookies disabled by default
- Framework: Next.js 16 with App Router and React 19
- Styling:
Tailwind CSS 4
with
@tailwindcss/typography - Animations: Framer Motion
- Internationalization: next-intl (en/sv)
- Content: Markdown processed via remark +
remark-gfmβrehype-pretty-codeβrehype-stringify - Syntax Highlighting: Shiki (build-time via rehype-pretty-code)
- Diagrams: Mermaid (lazy-loaded at runtime)
- Icons: Lucide React
- TypeScript: Strict mode with typed routes
- Unit Testing: Vitest with Testing Library and coverage via V8
- Integration Testing: Playwright
- Deployment: Cloudflare Workers via @opennextjs/cloudflare
app/[locale]/ β Pages (blog, team, cookies, privacy, terms)
app/api/analytics/ β Blog read tracking API endpoint
components/ β React components (client islands + shared UI)
content/blog/ β Blog posts in Markdown with frontmatter
lib/ β Utilities (blog, analytics, cookies, dates, i18n)
messages/{en,sv}.json β Translation files
public/ β Static assets, blog images, generated content
scripts/ β Build scripts (blog data, page dates, OG images, bundle analysis)
tests/integration/ β Playwright integration tests
See CONTRIBUTING.md for full setup instructions, development workflow, and environment configuration.
Quick start:
nvm install
nvm use
npm install
npm run devRun npm run dev:https to start the dev server over HTTPS on port 4443.
Next.js generates a self-signed certificate automatically. In a devcontainer the
host browser will show a "Not Secure" warning β click Advanced β Proceed to
continue. For a trusted certificate on bare-metal, install
mkcert on the host and run
mkcert -install before starting the dev server.
# Development
npm run dev # Start development server (http://localhost:3000)
npm run dev:https # Start development server with HTTPS (https://localhost:4443)
npm run build # Production build (runs prebuild automatically)
npm run preview # Build and preview via Cloudflare Workers locally
# Quality Assurance
npm run check # Run all checks (type-check, format, spell, lint, test, security)
npm run test # Run unit tests (Vitest)
npm run test:watch # Watch mode testing
npm run test:coverage # Coverage report
npm run test:ui # Vitest UI
npm run test:security # Security audit (sanitization tests)
npm run test:integration # Playwright integration tests (dev server)
npm run test:integration:preview # Playwright integration tests (preview server)
npm run lint # Biome linter (code)
npm run lint:md # markdownlint (Markdown)
npm run type-check # TypeScript checking
npm run format # Biome formatting
npm run spell # Spell checking (cspell)
# Build & Analysis
npm run build:sitedata # Rebuild blog data and page dates
npm run bundle:analyze # Analyze Cloudflare Worker bundle size
npm run clean:all # Remove .next, out, .open-next, .wrangler
# Deployment
npm run deploy # Build and deploy to Cloudflare WorkersThis project's source code is licensed under the MIT License β see the LICENSE file for details.
Specific assets such as logos and photographs of identifiable individuals are subject to different licensing terms. Please refer to the LICENSE-ASSETS.md file for details on the licensing of these assets.
- Blog posts and articles: Free to use, share, and adapt under the MIT License (see LICENSE).
- Source code: Open source under the MIT License (see LICENSE).
- Logos and Profile Photos: All Rights Reserved. See LICENSE-ASSETS.md for details.
- Other Assets in
public/directory: All Rights Reserved, unless otherwise specified. See LICENSE-ASSETS.md. - Personal/team information: Please respect privacy when reusing content.
The MIT License allows you to freely use the blog content and website source
code while ensuring proper attribution to Viscalyx. Other assets are subject to
the terms outlined in LICENSE-ASSETS.md.
Contributions are welcome! Please feel free to submit issues and pull requests.
See CONTRIBUTING.md for details on how to set up your environment and contribute to the project.