Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions .claude/skills/astrodb-website/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
name: astrodb-website
description: Set up and run a web interface for an AstroDB database using the Astro-Web template. Use this skill whenever a user wants to "view the database in a browser", "start the web interface", "see the data", or "set up the website".
compatibility: python, fastapi, uvicorn
---

# AstroDB Website

This skill sets up a FastAPI web interface ([Astro-Web](https://github.com/astrodbtoolkit/Astro-Web)) in your project directory to browse and visualize an AstroDB SQLite database.

## Prerequisites

- An existing AstroDB SQLite database (`.sqlite` or `.db`).
- `uv` installed.
- Python 3.13+.

## Step 1: Clone the Astro-Web Repository

The website should be set up in a directory named `website/` (or similar) in your project root. If it doesn't exist, clone it:

```bash
git clone https://github.com/astrodbtoolkit/Astro-Web website
```

Or, if the user prefers a submodule:
```bash
git submodule add https://github.com/astrodbtoolkit/Astro-Web website
```

## Step 2: Set up the Website Configuration

Use the bundled setup script to generate the `.env` file. You must point it to the database file and the directory where you cloned the website.

### Step 2.1: Verify Table and Column Names (Crucial)

Before running the setup script, verify the primary table name and coordinate columns:

1. **Check for primary table**: Run `sqlite3 <path-to-your-db>.sqlite ".tables"`
- If a table named `Sources` or `sources` is not found, **ask the user** what the primary sources table is.
2. **Check coordinate columns**: Run `sqlite3 <path-to-your-db>.sqlite "PRAGMA table_info(<primary_table>);"`
- Identify the RA and Dec column names (e.g., `ra` vs `ra_deg`).

### Step 2.2: Run Setup Script

Run the script with the verified table and column names:

```bash
uv run python .claude/skills/astrodb-website/scripts/setup_website.py \
--db-path <path-to-your-db>.sqlite \
--website-dir website/ \
--primary-table <primary_table_name> \
--ra-col <ra_column_name> \
--dec-col <dec_column_name>
```

The script will:
1. Create a `.env` file inside `website/`.
2. Configure it to point to your database.
3. Read `lookup_tables` from `database.toml` if it exists.
4. Set the primary table and coordinate column names.

## Step 3: Install Dependencies and Start the Server

```bash
cd website/
uv sync
uv run serve
```

Alternatively, you can run it manually with:
```bash
uv run uvicorn astro_web.main:app --reload --port 8000
```

## Step 4: Report Success

Inform the user that the website is running at **http://localhost:8000**.
Remind them they can stop the server with `Ctrl+C`.

## Troubleshooting

- **Database not found**: Ensure the `--db-path` provided to `setup_website.py` is correct.
- **Port already in use**: If 8000 is taken, use `--port <other-port>` with uvicorn.
- **Import errors**: Ensure `uv sync` was run in the `Astro-Web` directory.
106 changes: 106 additions & 0 deletions .claude/skills/astrodb-website/scripts/setup_website.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#!/usr/bin/env python
"""Setup script for Astro-Web skill.

Generates a .env file for Astro-Web based on a provided database path.
"""

import argparse
import sys
from pathlib import Path

import tomllib


def main():
parser = argparse.ArgumentParser(description="Setup Astro-Web .env file")
parser.add_argument("--db-path", required=True, help="Path to the SQLite database")
parser.add_argument("--website-dir", required=True, help="Directory where Astro-Web is cloned")
parser.add_argument("--toml-path", help="Path to database.toml (optional)")
parser.add_argument("--ra-col", default="ra", help="Name of the RA column (default: ra)")
parser.add_argument("--dec-col", default="dec", help="Name of the Dec column (default: dec)")
parser.add_argument("--primary-table", default="Sources", help="Name of the primary sources table (default: Sources)")
args = parser.parse_args()

db_path = Path(args.db_path).resolve()
if not db_path.exists():
print(f"ERROR: Database file not found: {db_path}", file=sys.stderr)
sys.exit(1)

astro_web_dir = Path(args.website_dir).resolve()
if not astro_web_dir.exists():
print(f"ERROR: Website directory not found at {astro_web_dir}", file=sys.stderr)
sys.exit(1)

# Look for database.toml
toml_path = None
if args.toml_path:
toml_path = Path(args.toml_path).resolve()
else:
# Check project root (2 levels up from skills/astrodb-website/)
root_toml = Path(__file__).parent.parent.parent.parent / "database.toml"
if root_toml.exists():
toml_path = root_toml
else:
# Check same dir as DB
db_dir_toml = db_path.parent / "database.toml"
if db_dir_toml.exists():
toml_path = db_dir_toml

lookup_tables = []
if toml_path and toml_path.exists():
print(f"Reading configuration from {toml_path}")
if tomllib:
try:
with open(toml_path, "rb") as f:
config = tomllib.load(f)
lookup_tables = config.get("lookup_tables", [])
except Exception as e:
print(f"WARNING: Could not parse {toml_path}: {e}")
else:
print("WARNING: tomllib not available, skipping database.toml parsing")

# Prepare .env content
# Use absolute path for database URL to avoid relative path confusion
db_url = f"sqlite:///{db_path}"

env_content = [
f'ASTRO_WEB_DATABASE_URL="{db_url}"',
'ASTRO_WEB_SCHEMA=""',
]

if lookup_tables:
env_content.append(f'ASTRO_WEB_LOOKUP_TABLES="{",".join(lookup_tables)}"')
else:
# Default lookup tables from Astro-Web .env.example
env_content.append(
'ASTRO_WEB_LOOKUP_TABLES="Publications,Telescopes,Instruments,PhotometryFilters,Versions,RegimeList,SourceTypeList,ParameterList,AssociationList,CompanionList,Modes,Filters,Citations,References,Parameters,Regimes"'
)

# Add other defaults
env_content.extend(
[
f'ASTRO_WEB_PRIMARY_TABLE="{args.primary_table}"',
'ASTRO_WEB_SOURCE_COLUMN="source"',
'ASTRO_WEB_FOREIGN_KEY="source"',
'ASTRO_WEB_PRIMARY_DATATYPE="str"',
f'ASTRO_WEB_RA_COLUMN="{args.ra_col}"',
f'ASTRO_WEB_DEC_COLUMN="{args.dec_col}"',
'ASTRO_WEB_SPECTRA_URL_COLUMN="access_url"',
'ASTRO_WEB_SOURCE_URL_BASE="/source/"',
]
)

env_path = astro_web_dir / ".env"
with open(env_path, "w") as f:
f.write("\n".join(env_content) + "\n")

print(f"Successfully generated {env_path}")
print("\nNext steps:")
print(f" cd {astro_web_dir.relative_to(Path.cwd())}")
print(" uv sync")
print(" uv run serve # Recommended")
print(" # OR: uv run uvicorn astro_web.main:app --reload --port 8000")


if __name__ == "__main__":
main()
Empty file added .gitmodules
Empty file.