#!/usr/bin/env python3 """ DreamWiki - A Single-File, AI-Generated Wikipedia Clone A web application that generates Wikipedia-style articles on-demand using LLMs via OpenRouter API. """ import os import re import json from pathlib import Path from typing import Optional import uvicorn from fastapi import FastAPI, HTTPException from fastapi.responses import HTMLResponse from dotenv import load_dotenv import requests import markdown2 from jinja2 import Template # ============================================================================ # Configuration # ============================================================================ # Load environment variables load_dotenv() # Constants PAGES_DIR = Path("pages") OPENROUTER_API_URL = "https://openrouter.ai/api/v1/chat/completions" # System prompt for article generation SYSTEM_PROMPT = """You are an encyclopedia author for a fictional, dream-like universe called DreamWiki. Your sole purpose is to generate complete, imaginative, and engaging encyclopedia articles. You must follow these rules strictly: 1. Your entire response must be in Markdown format. 2. The article should be comprehensive, with a short introductory paragraph followed by several sections (e.g., ## History, ## Characteristics, ## In Popular Culture). 3. You MUST invent and include 3-5 links to other DreamWiki articles. The links must be relevant and use the exact format: `[Link Text](/wiki/Article_Title)`. Do not use full URLs. 4. You MUST include at least one Markdown table. 5. You MUST include at least one placeholder image using the format ``. 6. Do not add any commentary, preamble, or sign-off. Respond only with the Markdown content of the article.""" # ============================================================================ # Templates and Styling # ============================================================================ CSS_STYLE = """ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Lato, Helvetica, Arial, sans-serif; line-height: 1.6; color: #222; max-width: 960px; margin: 0 auto; padding: 20px; background-color: #f8f9fa; } .header { border-bottom: 3px solid #a2a9b1; padding-bottom: 10px; margin-bottom: 20px; } .header h1 { margin: 0; color: #000; font-size: 2.2em; font-weight: normal; } .content { background: white; padding: 30px; border: 1px solid #a2a9b1; border-radius: 2px; } h1, h2, h3, h4, h5, h6 { color: #000; border-bottom: 1px solid #eaecf0; padding-bottom: 2px; margin-top: 30px; margin-bottom: 15px; } h1 { font-size: 2.2em; } h2 { font-size: 1.8em; } h3 { font-size: 1.4em; } a { color: #0645ad; text-decoration: none; } a:hover { text-decoration: underline; } a:visited { color: #0b0080; } table { border-collapse: collapse; margin: 20px 0; width: 100%; } table, th, td { border: 1px solid #a2a9b1; } th, td { padding: 8px 12px; text-align: left; } th { background-color: #eaecf0; font-weight: bold; } img { max-width: 100%; height: auto; margin: 15px 0; } .search-form { margin: 20px 0; } .search-input { padding: 8px 12px; font-size: 16px; border: 1px solid #a2a9b1; border-radius: 2px; width: 300px; } .search-button { padding: 8px 16px; font-size: 16px; background-color: #0645ad; color: white; border: none; border-radius: 2px; cursor: pointer; margin-left: 5px; } .search-button:hover { background-color: #0b0080; } .intro { background-color: #f8f9fa; padding: 20px; border-left: 5px solid #36c; margin: 20px 0; } """ HTML_TEMPLATE = """
DreamWiki is a fictional encyclopedia where every article is generated on-demand by artificial intelligence. Enter any topic below and watch as an entire article materializes from the digital ether, complete with interconnected lore and references to other dream-like entities.
Note: This is a creative experiment. All content is fictional and generated by AI.
Try searching for anything that comes to mind: fictional creatures, imaginary places, made-up technologies, or abstract concepts. Each search creates a new page in our ever-expanding dream universe.
""" template = Template(HTML_TEMPLATE) return template.render( title="Home", style=CSS_STYLE, content=content ) @app.get("/wiki/{page_title:path}", response_class=HTMLResponse) async def wiki_page(page_title: str): """Render a wiki page, generating it if it doesn't exist.""" title_slug = slugify(page_title) if not title_slug: raise HTTPException(status_code=400, detail="Invalid page title") # Check if page exists if page_exists(title_slug): # Load existing page markdown_content = load_page(title_slug) else: # Generate new page try: markdown_content = generate_article(page_title) save_page(title_slug, markdown_content) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to generate article: {str(e)}") # Convert Markdown to HTML html_content = markdown2.markdown(markdown_content, extras=['tables', 'fenced-code-blocks']) # Render the final page template = Template(HTML_TEMPLATE) return template.render( title=page_title, style=CSS_STYLE, content=html_content ) # ============================================================================ # Main Execution # ============================================================================ if __name__ == "__main__": uvicorn.run("app:app", host="0.0.0.0", port=8000, reload=True)