django.moscow — Service Landing with Design System
Production-ready landing page with auto-generated color palettes, custom ESLint rules, and strict FSD architecture. Built a next-level design system for scalable projects.
Table of Contents
Context
Launched a new Django support service and needed a landing page. But not just a "simple page" — a full-fledged platform for experimenting with design systems and architectural patterns. The result is a production-ready project with auto-generated color tokens, custom linters, and FSD architecture.
Live example: django.moscow
The project became a sandbox for testing advanced techniques: automatic design token generation, custom ESLint rules, strict FSD compliance. Everything that works here goes into commercial projects.
Next-Level Design System
Three-Layer Tokenization
Built a system where colors are automatically generated from config:
- Palettes (tokens.css) — 8 color palettes with 50-950 shades, generated from base colors via chroma-js in LCH color space
- Semantics (semantic.css) — contextual tokens (
background,foreground,surface,text-*,link) - Tailwind Mapping (theme-mapping.css) — seamless integration with utilities (
bg-surface,text-foreground)
// palette.config.json
{
"primary": { "base": "#7e102e" }
}npm run colors:generate
# → Generates full palette: primary-50...primary-950
# → Automatically configures dark mode (reversed scale)
# → Maps to Tailwind classesAutomatic Theme Support
Themes work via data-theme attribute, not classes:
:root {
--background: var(--color-gray-50);
--foreground: var(--color-gray-900);
}
[data-theme="dark"] {
--background: var(--color-gray-950);
--foreground: var(--color-gray-50);
}Custom ESLint Plugin
Built a custom ESLint plugin to prevent hardcoded colors:
// ❌ Forbidden
<div className="bg-blue-500 text-zinc-900" />
// ✅ Allowed
<div className="bg-primary-500 text-foreground" />The plugin analyzes:
- Tailwind classes in JSX (
className,class) - Inline styles (
style) - CSS files via Stylelint
Result: 100% design token usage, zero "magic" colors in code.
Architecture: FSD with Boundaries
Applied strict Feature-Sliced Design with automatic boundary enforcement:
src/
├── app/ # Next.js App Router, providers, global styles
├── processes/ # Business processes (checkout, onboarding)
├── widgets/ # Large UI blocks (header, footer, hero)
├── features/ # User scenarios (theme-toggle, filters)
├── entities/ # Domain entities (user, post, order)
└── shared/ # UI primitives, utilities, configImport Rules (enforced by ESLint):
features→ can importentities,sharedfeatures→ CANNOT importwidgets,processes- Violation = build error
ESLint shows no mercy: trying to import a widget into a feature = red build. It's strict control, but it pays off in the long run.
Tech Stack
Next.js 16 + React 19
Used the latest versions to test new capabilities:
- Server Components by default
- Server Actions for forms
- Streaming and Suspense
- Optimized Turbopack build (in dev mode)
Tailwind CSS v4
New version with inline config directly in CSS:
@theme inline {
--color-primary: var(--primary);
--color-foreground: var(--foreground);
}No tailwind.config.js — everything in CSS, native and fast.
shadcn/ui Integration
Configured components.json to work with FSD:
npx shadcn@latest add button
# → Installs to src/shared/ui/
# → Integrates with design tokens
# → Ready to useContent and SEO
MDX Blog with Validation
- All posts in MDX with frontmatter
- Zod schema for metadata validation
- Automatic validation in pre-push hook
- Separate script for CI/CD:
npm run blog:validate
Full SEO Optimization
- JSON-LD structured data (Organization, WebSite, Service)
- Dynamic sitemap
- robots.txt
- Open Graph and Twitter Cards
- Canonical URLs
const jsonLd = {
"@context": "https://schema.org",
"@type": "Service",
name: "Django Support and Development",
provider: { "@id": "https://django.moscow/#organization" },
};Production-Ready Infrastructure
PM2 in Cluster Mode
// ecosystem.config.js
{
name: 'django-moscow',
instances: 'max', // All CPU cores
exec_mode: 'cluster', // Cluster for zero-downtime
autorestart: true, // Auto-restart on crash
max_memory_restart: '1G', // Restart on memory limit
}Zero-downtime deploys:
pm2 reload django-moscow # Restart without downtimeGit Hooks for Quality
- pre-commit: ESLint + Stylelint (blocks commit on errors)
- pre-push: MDX posts validation (blocks push on invalid data)
Results
Lessons Learned
Token Auto-Generation = Scalability
Adding a new color to the design system is now changing 1 line in JSON and running a script. Previously — an hour of manual work.
Custom ESLint Rules Pay Off
The first 2 days I complained about the "annoying linter". A week later — appreciated the absence of questions like "why does the button have the wrong color in dark mode?".
FSD with Boundaries ≠ Bureaucracy
Strict import rules seem excessive at the start. After a month of development, you realize it's the only way to prevent the project from turning into spaghetti.
django.moscow became a testing ground for techniques I now apply in all projects: auto-generated design tokens, custom linters, strict FSD. The result is predictable, scalable, and pleasant-to-maintain code.
What's Next
- RSS/Atom feed for blog
- Auto-generated OG images for posts
- Lighthouse CI in pipeline
- A/B testing on landing
- Design system expansion: spacing, typography, shadows
Similar projects
Projects with similar technologies and tasks
PassWave — Password Generator & Vault
Minimalist PWA: generates strong passwords, encrypts everything on the client, syncs if you want. Built the MVP in 2 weeks — kept it as is: fast, safe, no bloat.
- Next.js 16
- React 19
- TypeScript
- Supabase
- PWA
- +1
Slot‑Me.ru — Meeting Booking Platform
Cal.com for the Russian market: from architecture to production. FastAPI + React, FSD, OAuth, calendars, email, 196 tests.
- FastAPI
- React
- PostgreSQL
- Redis
- TypeScript
- +3
EEF (SCO) — Youth Economic Forum Management System
Government contract to run a large international event: 12 curators, 72 local coordinators, 5000+ participants. Technically flawless, psychologically exhausting. A lesson that gov contracts require both technology and people work.
- Python
- Django
- PostgreSQL
- JavaScript
- jQuery
- +1