Skip to content
Back to skills

Public Website

ASecurity

Guides the agent to create professional public websites with React/MUI served from the project's /web subdirectory with hot-reloadable API endpoints

  • 32 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 3, 2026
ai-agentsjavascriptpythongojavabashreactflaskapifrontend

Works with

  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 3, 2026

npx -y skills add BulloRosso/etienne --skill public-website --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Public Website?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Public Website
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/bullorosso-public-website/badge)](https://www.skillsdirectory.com/skills/bullorosso-public-website)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: public-website
description: Guides the agent to create professional public websites with React/MUI served from the project's /web subdirectory with hot-reloadable API endpoints
---
# Public Website

This skill enables you to create professional, publicly accessible websites for projects. Websites are served from the project's `/web` subdirectory and are accessible via the webserver.

## When to Use This Skill

Use this skill when the user asks you to:
- Create a public website or landing page for a project
- Build a web application with API endpoints
- Create forms, questionnaires, or interactive pages
- Set up a web presence for data collection or presentation

## Architecture

### URL Structure
- **Static pages**: `/web/<project>/index.html`, `/web/<project>/about.html`
- **Assets**: `/web/<project>/css/styles.css`, `/web/<project>/js/app.js`
- **API endpoints**: `/web/<project>/api/<endpoint-name>`

### Directory Structure
```
workspace/<project>/
├── web/                    # Static website content (HTML, CSS, JS, images)
│   ├── index.html          # Start document (required)
│   ├── css/
│   │   └── styles.css
│   ├── js/
│   │   └── app.js
│   └── images/
└── api/                    # API endpoint Python files (hot-reloadable)
    └── <endpoint>.py
```

### Technology Stack
- **Frontend**: React 18 via CDN (no build step required)
- **UI Library**: Material-UI (MUI) v5 + MUI Icons via CDN
- **API**: Python endpoint files with hot-reload (Flask request/response)
- **No authentication**: The website is public and does not require any form of authentication

## Step 1: Ask the User About Language

Before creating any content, ask the user which language(s) the website should support. The user may want a German website even though the conversation is in English. Supported patterns:
- Single language (e.g., German only)
- Multi-language with language switcher using localStorage to remember the choice

## Step 2: Create the Directory Structure

```bash
mkdir -p web
mkdir -p web/css
mkdir -p web/js
mkdir -p web/images
mkdir -p api
```

## Step 3: Create index.html

The start document must be located at `web/index.html`. Use this template:

```html
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Project Title</title>

    <!-- React -->
    <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

    <!-- MUI -->
    <script crossorigin src="https://unpkg.com/@mui/material@5/umd/material-ui.production.min.js"></script>

    <!-- Roboto Font -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" />

    <!-- Material Icons Font -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
</head>
<body>
    <div id="root"></div>
    <script type="text/babel">
        const {
            ThemeProvider, createTheme, CssBaseline,
            AppBar, Toolbar, Typography, Container, Box, Button, Paper,
            IconButton, Grid, Card, CardContent, CardActions
        } = MaterialUI;

        const theme = createTheme();

        function App() {
            return (
                <ThemeProvider theme={theme}>
                    <CssBaseline />
                    {/* Your app content here */}
                </ThemeProvider>
            );
        }

        const root = ReactDOM.createRoot(document.getElementById('root'));
        root.render(<App />);
    </script>
</body>
</html>
```
In the App Bar include our company name "Music Parts GmbH" 

## Step 4: Create API Endpoints (if needed)

API endpoint files go in the `api/` directory. Each Python file becomes an endpoint automatically. The server hot-reloads when files change.

**File naming**: `api/<endpoint-name>.py` maps to URL `/web/<project>/api/<endpoint-name>`

### Pattern 1 - HTTP verb functions (preferred)

```python
# api/contact.py
import json
import os

DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))

def get(request=None):
    """Return existing submissions."""
    filepath = os.path.join(DATA_DIR, "data", "submissions.json")
    if not os.path.exists(filepath):
        return {"submissions": []}
    with open(filepath, encoding="utf-8") as f:
        return json.load(f)

def post(request):
    """Handle form submission."""
    data = request.get_json(silent=True) or {}
    filepath = os.path.join(DATA_DIR, "data", "submissions.json")

    existing = []
    if os.path.exists(filepath):
        with open(filepath, encoding="utf-8") as f:
            existing = json.load(f).get("submissions", [])

    existing.append(data)

    os.makedirs(os.path.dirname(filepath), exist_ok=True)
    with open(filepath, "w", encoding="utf-8") as f:
        json.dump({"submissions": existing}, f, indent=2, ensure_ascii=False)

    return {"success": True, "message": "Submission received"}
```

### Pattern 2 - handle() with SUPPORTED_METHODS

```python
SUPPORTED_METHODS = ["GET", "POST"]

def handle(request):
    if request.method == "GET":
        return {"status": "ok"}
    elif request.method == "POST":
        data = request.get_json(silent=True) or {}
        return {"received": data}
```

## Step 5: Calling APIs from the Frontend

Use `fetch()` with server-relative URLs. Replace `<project>` with the actual project name.

```javascript
// GET request
const response = await fetch('/web/<project>/api/contact');
const data = await response.json();

// POST request
const response = await fetch('/web/<project>/api/contact', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ name: 'John', message: 'Hello' })
});
```

## Design Guidelines

### Visual Design
- Use the MUI **default color theme** (primary: #1976d2 blue)
- Create a **calm and professional** appearance
- Use proper spacing and typography hierarchy
- Include responsive design for mobile devices

### Navigation & Links
- Always use server-relative links: `/web/<project>/page.html`
- Never use absolute URLs with localhost
- For single-page apps, use hash-based routing (`#/page`) or manage state in React

### User Settings
- Use **localStorage** to remember user settings and choices
- Examples: language preference, form progress, theme preference

## API Data Storage

API endpoints can read and write data in the project directory. Common patterns:
- Store form submissions in `data/submissions.json`
- Store user feedback in `data/feedback.json`
- Read configuration from `data/config.json`

The API has full access to the project directory, enabling:
- Web questionnaires that write results to the project folder
- Dashboards that read from project data files
- Forms that trigger project workflows

## Hot Reload

- **Static files**: Edit HTML/CSS/JS, refresh the browser
- **API endpoints**: Edit the Python file, the server detects changes and reloads the module automatically on the next request

## Notes

- The website is **public** -- no authentication required
- Always use `charset=utf-8` for proper encoding of non-ASCII characters
- Test the website by opening `/web/<project>/` in a browser
- The `web/` subdirectory is separate from other project directories like `data/`, `out/`, etc.

Files in this skill

  • SKILL.md7.3 KB
  • thumbnail.png6.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.