Official website for Frankencoin (ZCHF), a collateralized, oracle-free stablecoin that tracks the Swiss franc.
Frankencoin brings the strength of the Swiss franc on-chain as an ERC-20 token. In the last 50 years, the Swiss franc climbed more than 240% against the dollar, and now this stability is available in DeFi through Frankencoin (ZCHF).
The website is designed to be accessible to non-technical audiences, traditional finance professionals, and journalistsβfocusing on real-world use cases and practical applications rather than purely technical or crypto-focused messaging.
- Framework: Astro v5 - Static site generator with server-side rendering
- Styling: Tailwind CSS v4 - Utility-first CSS framework
- Interactivity: Alpine.js - Lightweight JavaScript framework for client-side reactivity
- Deployment: Node.js standalone mode via @astrojs/node
- Language: TypeScript for type safety
/
βββ public/
β βββ images/ # Static images, logos, and assets
β βββ fonts/ # Custom fonts (Avenir family)
β βββ favicon.svg
βββ src/
β βββ components/ # Reusable Astro components
β β βββ BadgeContainer/
β β βββ ChainCard/
β β βββ Tooltip/
β β βββ TabsMenu/
β β βββ MediaCarousel/
β β βββ FAQContainer/
β β βββ Layout/ # Header, Footer, Section, Base
β βββ content/ # JSON data files (content-first architecture)
β β βββ en/ # English content
β β β βββ index.json # Homepage content
β β β βββ use-cases.json # Real-world use cases
β β β βββ faq.json # FAQs
β β β βββ governance.json # Governance & FPS page
β β β βββ ecosystem.json # Ecosystem page
β β β βββ token.json # Token page
β β β βββ what-is-frankencoin.json
β β β βββ shared/ # English-specific shared content
β β β βββ site.json # Site metadata & SEO
β β β βββ nav.json # Navigation config
β β β βββ footer.json # Footer content
β β β βββ ui.json # UI text labels
β β βββ de/ # German content (same structure as en/)
β β βββ fr/ # French content (same structure as en/)
β β βββ shared/ # Globally shared content (all languages)
β β βββ media.json # Articles, videos, and metadata overrides
β βββ pages/ # Route pages
β β βββ index.astro # Homepage (English default)
β β βββ governance.astro
β β βββ ecosystem.astro
β β βββ token.astro
β β βββ use-cases.astro
β β βββ what-is-frankencoin.astro
β β βββ [lang]/ # Localized routes
β β βββ index.astro
β β βββ governance.astro
β β βββ ecosystem.astro
β β βββ token.astro
β β βββ use-cases.astro
β β βββ what-is-frankencoin.astro
β βββ styles/ # Global styles
β β βββ global.css
β β βββ tokens.css # Design tokens (CSS custom properties)
β β βββ typography.css
β β βββ fonts.css
β βββ utils/ # Utility functions
β βββ i18n.ts # Internationalization helpers
β βββ fetchOgData.ts # Open Graph metadata fetcher
β βββ fetchYouTubeData.ts # YouTube metadata fetcher
βββ package.json
All commands are run from the root of the project:
| Command | Action |
|---|---|
yarn install |
Installs dependencies |
yarn run dev |
Starts local dev server at localhost:3000 |
yarn run build |
Build production site to ./dist/ |
yarn run preview |
Preview production build locally |
yarn run astro ... |
Run CLI commands like astro add, astro check |
yarn run astro -- --help |
Get help using the Astro CLI |
The website supports multiple languages with a file-based content structure:
- English (en) - Default language at
/ - German (de) - Available at
/de/* - French (fr) - Available at
/fr/*
- English (default):
https://frankencoin.com/βsrc/content/en/ - German:
https://frankencoin.com/de/βsrc/content/de/ - French:
https://frankencoin.com/fr/βsrc/content/fr/
Content is organized into three levels:
-
Language-specific content (
src/content/{lang}/)- Page content files (index.json, governance.json, etc.)
- Unique to each language
-
Language-specific shared content (
src/content/{lang}/shared/)- Navigation, footer, site metadata, UI labels
- Shared across all pages within a language
-
Globally shared content (
src/content/shared/)- Media (articles, videos) with metadata
- Shared across ALL languages
The src/utils/i18n.ts file provides helper functions:
getLanguageFromURL(pathname)- Detects language from URLloadContent(file, lang)- Loads language-specific contentloadSharedContent(file, lang)- Loads language-specific shared contentloadGlobalSharedContent(file)- Loads globally shared contentgetLocalizedPath(path, lang)- Generates localized URLs
- Create new language folder:
src/content/{lang}/ - Copy all JSON files from
src/content/en/tosrc/content/{lang}/ - Create
src/content/{lang}/shared/folder - Copy shared files from
src/content/en/shared/tosrc/content/{lang}/shared/ - Translate all content in the JSON files
- Add language to
src/utils/i18n.ts:export const languages = { en: 'English', de: 'Deutsch', fr: 'FranΓ§ais', // Add new language here };
- Update language selector in header component
- Homepage (
/): Hero section, live stats, what is Frankencoin, how it works, foundation/FPS overview, trust & security, media articles, videos, and FAQs - Governance (
/governance): FPS information, governance model, how to acquire FPS, and participation details - Use Cases (
/use-cases): Real-world applications categorized by Payments, Business, and DeFi with partner showcases and filterable interface - What is Frankencoin (
/what-is-frankencoin): Educational content about the stablecoin for non-technical audiences - Token (
/token): ZCHF token information across different blockchain networks - Ecosystem (
/ecosystem): Overview of the Frankencoin ecosystem - FPS (
/fps): Frankencoin Pool Shares detailed information
- Tooltip Component: Copy-to-clipboard functionality with Alpine.js state management
- TabMenu Component: Tabbed interface for system workflow visualization
- ChainCard Component: Display blockchain network information
- BadgeContainer: Responsive stats display with hover effects
- MediaCarousel: Unified carousel combining articles and videos with automatic metadata fetching
- Use Cases Filtering: Category-based filtering with Alpine.js (Payments, Business, DeFi)
- Content-First Architecture: All page content separated into dedicated JSON files under
src/content/media.json- Articles, videos, and metadata overridesuse-cases.json- Real-world use cases with partner informationfaq.json- Frequently asked questions by categorygovernance.json- Governance and FPS content
- Separation of Content and Logic: Content updates don't require touching component code
- Dynamic Data Fetching: Live stats from Frankencoin API at build time
- Open Graph Metadata: Automatic fetching of article metadata with manual override support
- Custom Typography: Avenir font family with predefined type scales
- Responsive Design: Mobile-first approach with Tailwind breakpoints
- Brand Colors: Swiss-inspired color palette via CSS custom properties
- Component Library: Reusable, composable components with TypeScript interfaces
The file public/llms.txt provides structured information about Frankencoin for AI crawlers and large language models (following the llms.txt specification). It contains:
- Protocol overview and key facts
- Links to documentation, audits, legal classifications
- Source code repositories
- Community channels and contact info
- Reference to the MCP Server for machine-readable protocol data
Updating llms.txt: Edit public/llms.txt directly. Keep it factual and concise β this is what ChatGPT, Claude, Perplexity, and other AI systems read when users ask about Frankencoin. Rebuild the site after changes.
Verify: curl -s https://frankencoin.com/llms.txt | head -1 should return # Frankencoin (plain text, not HTML).
AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, etc.) are explicitly allowed in public/robots.txt. Do not add Disallow rules for AI user agents unless there is a specific reason.
The Frankencoin MCP server at mcp.frankencoin.com provides a machine-readable interface for AI agents to query live protocol data (supply, positions, challenges, etc.). It is referenced in llms.txt and should be kept in sync if the URL changes.
- Live Website: frankencoin.com
- Web App: app.frankencoin.com
- Documentation: docs.frankencoin.com
- API: api.frankencoin.com
- GitHub: Frankencoin Organization
- DeFiLlama: defillama.com/protocol/frankencoin
- CoinGecko: coingecko.com/en/coins/frankencoin
- Node.js 18+
- npm or yarn
# Clone the repository
git clone https://github.com/Frankencoin-ZCHF/frankencoin-site.git
cd frankencoin-site
# Install dependencies
yarn install
# Start development server
yarn run devThe development server will start at http://localhost:3000 (or the next available port if 3000 is in use).
# Build the site
yarn run build
# Preview the build
yarn run previewSITE: Base URL for the site (default:https://frankencoin.com)PORT: Development server port (default:3000)
All website content is managed through JSON files in src/content/. This content-first architecture separates content from code, making updates simple and safe.
- Language-specific content: Files in
src/content/{lang}/contain translated text for each language - Globally shared content: Files in
src/content/shared/are used across all languages (e.g., media articles/videos)
Articles appear in the "In the Media" section on the homepage and are shared across all languages.
File: src/content/shared/media.json
- Add the article URL to the
articlesarray:
{
"articles": [
"https://example.com/new-article-url",
"https://existing-article.com/..."
]
}-
The system automatically fetches Open Graph metadata (title, description, image, etc.) from the URL at build time.
-
Optional: To override specific metadata fields, add an entry to the
articleMetadataobject:
{
"articleMetadata": {
"https://example.com/new-article-url": {
"title": "Custom Title Override",
"description": "Custom description...",
"image": "https://example.com/custom-image.jpg",
"publishedDate": "Jan 15, 2026",
"siteName": "Publication Name"
}
}
}Note: Only include fields you want to override. The system will use fetched Open Graph data for any fields not specified. Articles appear the same on all language versions of the site.
Videos appear in the "Frankencoin Explained" section on the homepage and are shared across all languages.
File: src/content/shared/media.json
Add YouTube video URLs to the videos array:
{
"videos": [
"https://www.youtube.com/watch?v=VIDEO_ID",
"https://youtu.be/ANOTHER_VIDEO_ID"
]
}To override video metadata, add to the videoMetadata object:
{
"videoMetadata": {
"https://www.youtube.com/watch?v=VIDEO_ID": {
"title": "Custom Video Title",
"description": "Custom description...",
"author": "Channel Name",
"publishedDate": "Dec 31, 2025"
}
}
}The video carousel will automatically display the new videos across all languages.
Use cases are displayed on the /use-cases page with category filtering and are language-specific.
Files:
- English:
src/content/en/use-cases.json - German:
src/content/de/use-cases.json - French:
src/content/fr/use-cases.json
Add a new use case to the cases array in each language file:
{
"cases": [
{
"category": "Payments",
"title": "New Use Case Title",
"description": "Description of the use case...",
"image": "/images/use-case-image.webp",
"logo": "/images/partner-logo.svg",
"partnerName": "Partner Company Name",
"link": "https://partner-website.com"
}
]
}Available categories: Payments, Business, DeFi
FAQs are organized by category, displayed on the homepage, and are language-specific.
Files:
- English:
src/content/en/faq.json - German:
src/content/de/faq.json - French:
src/content/fr/faq.json
Add a new question to an existing category in each language file:
{
"categories": [
{
"category": "Basics",
"questions": [
{
"question": "Your new question?",
"answer": "Your answer here. You can use [markdown links](https://example.com) in answers."
}
]
}
]
}Or add a new category:
{
"categories": [
{
"category": "New Category Name",
"questions": [
{
"question": "First question in new category?",
"answer": "Answer with [markdown links](https://example.com) supported."
}
]
}
]
}Markdown support: Use [text](url) for links in answers. They'll automatically open in new tabs.
Homepage content is language-specific.
Files:
- English:
src/content/en/index.json - German:
src/content/de/index.json - French:
src/content/fr/index.json
The homepage content includes:
hero- Hero section with title, subtitle, and CTAstats- Live statistics (fetched from API at build time)what_is- "What is Frankencoin" sectioncore_features- Feature cardshow_it_works- How it works explanationfoundation- FPS and foundation informationtrust_security- Trust & security sectionin_the_media- Media section headersvideos- Video section headers
Edit the relevant section in the JSON file to update content.
Governance content is language-specific.
Files:
- English:
src/content/en/governance.json - German:
src/content/de/governance.json - French:
src/content/fr/governance.json
The governance page includes:
header- Page title, subtitle, image, and CTA buttonscaps- FPS metrics (price, supply, market cap)stats_list- Reserve statisticssections- Content sections explaining governance
To add a new CTA button:
{
"header": {
"cta": [
{
"label": "Button Text",
"href": "https://app.frankencoin.com/path",
"external": true
}
]
}
}- Always validate JSON syntax before committing (use a JSON validator or your IDE)
- Use meaningful names for images and upload them to
/public/images/ - Keep descriptions concise and accessible to non-technical audiences
- Test locally after content changes to verify formatting
- Use relative links (
/#section-id) for internal navigation - Use absolute URLs with
https://for external links - Optimize images before uploading (use
.webpformat when possible)
Some data is fetched live at build time:
- Homepage stats (TVL, Total Supply, FPS Market Cap) - from
https://api.frankencoin.com/ecosystem/frankencoin/info - Governance metrics (FPS Price, Supply, Reserve data) - from
https://api.frankencoin.com/ecosystem/fps/info - Article metadata - from Open Graph tags on article URLs
These update automatically when you rebuild the site.
Common content management tasks:
| Task | File | Shared Across Languages? |
|---|---|---|
| Add article | src/content/shared/media.json |
β Yes - Same for all languages |
| Add video | src/content/shared/media.json |
β Yes - Same for all languages |
| Override article metadata | src/content/shared/media.json |
β Yes - Same for all languages |
| Override video metadata | src/content/shared/media.json |
β Yes - Same for all languages |
| Add use case | src/content/{lang}/use-cases.json |
β No - Translate for each language |
| Add FAQ | src/content/{lang}/faq.json |
β No - Translate for each language |
| Update hero text | src/content/{lang}/index.json |
β No - Translate for each language |
| Update governance CTAs | src/content/{lang}/governance.json |
β No - Translate for each language |
| Update navigation | src/content/{lang}/shared/nav.json |
β No - Translate for each language |
| Update footer | src/content/{lang}/shared/footer.json |
β No - Translate for each language |
| Update site metadata | src/content/{lang}/shared/site.json |
β No - Translate for each language |
| Update UI labels | src/content/{lang}/shared/ui.json |
β No - Translate for each language |
Note: Replace {lang} with en, de, or fr depending on the language.
After making changes, rebuild the site to see updates.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Test thoroughly locally
- Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License.