mirror of
https://github.com/alexandrev/xslt-lab.git
synced 2026-09-14 09:03:15 +00:00
Add SEO improvements and CLAUDE.md
- Add visually hidden H1 for search engines and screen readers - Add JSON-LD structured data (WebApplication schema) - Add subtle footer tagline with keywords - Use semantic H1 in loading shell - Add CLAUDE.md for Claude Code guidance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
XSLT Lab is an online XSLT editor and tester that uses Saxon for XSLT 2.0/3.0 transformations. The application consists of a React frontend and a Go backend that orchestrates Java/Saxon for XSLT processing.
|
||||||
|
|
||||||
|
## Build Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Full stack with Docker Compose (lightweight, no database)
|
||||||
|
make compose-up
|
||||||
|
make compose-down
|
||||||
|
|
||||||
|
# Backend (Go)
|
||||||
|
cd backend/src && go build -o ../server
|
||||||
|
cd backend && ./server
|
||||||
|
|
||||||
|
# Frontend (React/Vite)
|
||||||
|
cd frontend && npm install
|
||||||
|
VITE_BACKEND_URL=http://localhost:8000 npm run dev
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
make backend-test # Go tests: go test ./...
|
||||||
|
make frontend-test # npm tests: vitest
|
||||||
|
|
||||||
|
# Docker images
|
||||||
|
make backend-image
|
||||||
|
make frontend-image
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Frontend (`/frontend`)
|
||||||
|
- React 18 + Vite SPA
|
||||||
|
- **App.jsx** is the monolithic state container managing all workspace state, tabs, transformations
|
||||||
|
- Monaco Editor for code editing (lazy-loaded)
|
||||||
|
- LocalStorage persistence for workspace data (up to 3 workspaces)
|
||||||
|
- `/lib/workspaceUtils.js` contains utility functions for parameter extraction, error parsing, XSLT manipulation
|
||||||
|
|
||||||
|
### Backend (`/backend`)
|
||||||
|
- Go/Gin HTTP server on port 8000
|
||||||
|
- Executes Saxon via `java` command with generated args file
|
||||||
|
- **POST /transform** - Main endpoint accepting `{xslt, version, parameters, trace}`
|
||||||
|
- 10-second timeout per transformation
|
||||||
|
- `/ext/` contains Java custom extension functions (uuid, date, base64, etc.)
|
||||||
|
|
||||||
|
### Data Flow
|
||||||
|
```
|
||||||
|
Frontend (POST /transform) → Go Backend → java/Saxon → Parse trace/result → JSON response
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pro Features (when VITE_GO_PRO=true)
|
||||||
|
- Firebase authentication
|
||||||
|
- PostgreSQL history storage
|
||||||
|
- `/history` endpoint
|
||||||
|
|
||||||
|
## Key Environment Variables
|
||||||
|
|
||||||
|
**Frontend (build-time)**:
|
||||||
|
- `VITE_BACKEND_URL` - Backend API endpoint
|
||||||
|
- `VITE_GO_PRO` - Enable Pro features
|
||||||
|
- `VITE_FIREBASE_CONFIG` - Firebase configuration
|
||||||
|
|
||||||
|
**Backend**:
|
||||||
|
- `DATABASE_URL` - PostgreSQL connection (Pro mode)
|
||||||
|
- `SAXON_CLASSPATH` - Path to Saxon JARs (default in app.config)
|
||||||
|
|
||||||
|
## Configuration Files
|
||||||
|
|
||||||
|
- `/backend/app.config` - Backend port and Saxon classpath
|
||||||
|
- `/docker-compose.local.yml` - Lightweight dev stack (no DB)
|
||||||
|
- `/docker-compose.yml` - Full stack with PostgreSQL
|
||||||
|
- `/charts/xslt-playground/` - Helm chart for Kubernetes deployment
|
||||||
+26
-1
@@ -22,6 +22,30 @@
|
|||||||
<meta property="og:image" content="/logo.svg" />
|
<meta property="og:image" content="/logo.svg" />
|
||||||
<link rel="canonical" href="https://xsltplayground.com/" />
|
<link rel="canonical" href="https://xsltplayground.com/" />
|
||||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "WebApplication",
|
||||||
|
"name": "XSLT Playground",
|
||||||
|
"alternateName": "XSLT Lab",
|
||||||
|
"url": "https://xsltplayground.com/",
|
||||||
|
"description": "Free online XSLT editor, tester and optimizer. Transform XML documents with XSLT 1.0 and 2.0 stylesheets using Saxon processor.",
|
||||||
|
"applicationCategory": "DeveloperApplication",
|
||||||
|
"operatingSystem": "Any",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "0",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
},
|
||||||
|
"featureList": [
|
||||||
|
"XSLT 1.0 and 2.0 support",
|
||||||
|
"Real-time XML transformation",
|
||||||
|
"Multiple workspaces",
|
||||||
|
"Variable tracing",
|
||||||
|
"Import/Export workspaces"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -48,6 +72,7 @@
|
|||||||
.shell-title {
|
.shell-title {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
.shell-subtitle {
|
.shell-subtitle {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
@@ -109,7 +134,7 @@
|
|||||||
<div class="shell-top">
|
<div class="shell-top">
|
||||||
<img src="/logo.svg" alt="XSLT Playground logo" class="shell-logo" />
|
<img src="/logo.svg" alt="XSLT Playground logo" class="shell-logo" />
|
||||||
<div>
|
<div>
|
||||||
<div class="shell-title">XSLT Playground</div>
|
<h1 class="shell-title">XSLT Playground</h1>
|
||||||
<div class="shell-subtitle">Loading the editor...</div>
|
<div class="shell-subtitle">Loading the editor...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1304,6 +1304,7 @@ export default function App() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="app-container">
|
<div className="app-container">
|
||||||
|
<h1 className="sr-only">XSLT Playground - Online XSLT Editor and Tester</h1>
|
||||||
{ethicalAdsEnabled && (
|
{ethicalAdsEnabled && (
|
||||||
<div
|
<div
|
||||||
ref={ethicalSlotRef}
|
ref={ethicalSlotRef}
|
||||||
@@ -1894,6 +1895,7 @@ export default function App() {
|
|||||||
<div className="footer-left">
|
<div className="footer-left">
|
||||||
<img src={logo} alt="XSLT Playground logo" className="logo" />
|
<img src={logo} alt="XSLT Playground logo" className="logo" />
|
||||||
<strong>xsltplayground.com</strong>
|
<strong>xsltplayground.com</strong>
|
||||||
|
<span className="footer-tagline">Free XSLT Editor & Tester</span>
|
||||||
<a
|
<a
|
||||||
className="news-link"
|
className="news-link"
|
||||||
href={newsUrl}
|
href={newsUrl}
|
||||||
|
|||||||
@@ -7,6 +7,18 @@ body,
|
|||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
a:focus-visible {
|
a:focus-visible {
|
||||||
outline: none;
|
outline: none;
|
||||||
box-shadow: 0 0 0 2px rgba(74, 133, 255, 0.35);
|
box-shadow: 0 0 0 2px rgba(74, 133, 255, 0.35);
|
||||||
@@ -867,6 +879,13 @@ a:focus-visible {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footer-tagline {
|
||||||
|
color: #536084;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
.footer-theme-toggle {
|
.footer-theme-toggle {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
@@ -1367,6 +1386,11 @@ a:focus-visible {
|
|||||||
color: #c7d2e3;
|
color: #c7d2e3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root[data-theme="dark"] .footer-tagline {
|
||||||
|
color: #8a9ab8;
|
||||||
|
border-left-color: #3a4659;
|
||||||
|
}
|
||||||
|
|
||||||
:root[data-theme="dark"] .icon-button {
|
:root[data-theme="dark"] .icon-button {
|
||||||
color: #c7d2e3;
|
color: #c7d2e3;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user