Răsfoiți Sursa

Generate app sitemap (#552)

Nikhil Rao 2 ani în urmă
părinte
comite
d72256d427

BIN
pynecone/.templates/web/bun.lockb


+ 2 - 1
pynecone/.templates/web/package.json

@@ -2,7 +2,7 @@
   "name": "pynecone",
   "scripts": {
     "dev": "next dev",
-    "export": "next build && next export -o _static",
+    "export": "next build && next-sitemap && next export -o _static",
     "prod": "next start"
   },
   "dependencies": {
@@ -17,6 +17,7 @@
     "gridjs": "^4.0.0",
     "gridjs-react": "^4.0.0",
     "next": "^12.1.0",
+    "next-sitemap": "^3.1.52",
     "plotly.js": "2.6.4",
     "prettier": "^2.8.1",
     "react": "^17.0.2",

+ 3 - 0
pynecone/compiler/templates.py

@@ -193,3 +193,6 @@ SOCKET = "const socket = useRef(null)"
 
 # Color toggle
 COLORTOGGLE = f"const {{ {constants.COLOR_MODE}, {constants.TOGGLE_COLOR_MODE} }} = {constants.USE_COLOR_MODE}()"
+
+# Sitemap config file.
+SITEMAP_CONFIG = "module.exports = {config}".format

+ 5 - 2
pynecone/config.py

@@ -21,6 +21,9 @@ class Config(Base):
     # The backend API url.
     api_url: str = constants.API_URL
 
+    # The deploy url.
+    deploy_url: Optional[str] = None
+
     # The database url.
     db_url: Optional[str] = constants.DB_URL
 
@@ -30,8 +33,8 @@ class Config(Base):
     # Telemetry opt-in.
     telemetry_enabled: bool = True
 
-    # The deploy url.
-    deploy_url: Optional[str] = None
+    # The pcdeploy url.
+    pcdeploy_url: Optional[str] = None
 
     # The environment mode.
     env: constants.Env = constants.Env.DEV

+ 2 - 0
pynecone/constants.py

@@ -50,6 +50,8 @@ WEB_STATIC_DIR = os.path.join(WEB_DIR, "_static")
 WEB_UTILS_DIR = os.path.join(WEB_DIR, UTILS_DIR)
 # The directory where the assets are located.
 WEB_ASSETS_DIR = os.path.join(WEB_DIR, "public")
+# The sitemap config file.
+SITEMAP_CONFIG_FILE = os.path.join(WEB_DIR, "next-sitemap.config.js")
 # The node modules directory.
 NODE_MODULES = "node_modules"
 # The package lock file.

+ 12 - 5
pynecone/pc.py

@@ -129,14 +129,14 @@ def deploy(dry_run: bool = typer.Option(False, help="Whether to run a dry run.")
     config.api_url = utils.get_production_backend_url()
 
     # Check if the deploy url is set.
-    if config.deploy_url is None:
+    if config.pcdeploy_url is None:
         typer.echo("This feature is coming soon!")
         return
 
     # Compile the app in production mode.
     typer.echo("Compiling production app")
     app = utils.get_app().app
-    utils.export_app(app, zip=True)
+    utils.export_app(app, zip=True, deploy_url=config.deploy_url)
 
     # Exit early if this is a dry run.
     if dry_run:
@@ -144,7 +144,7 @@ def deploy(dry_run: bool = typer.Option(False, help="Whether to run a dry run.")
 
     # Deploy the app.
     data = {"userId": config.username, "projectId": config.app_name}
-    original_response = httpx.get(config.deploy_url, params=data)
+    original_response = httpx.get(config.pcdeploy_url, params=data)
     response = original_response.json()
     frontend = response["frontend_resources_url"]
     backend = response["backend_resources_url"]
@@ -175,15 +175,22 @@ def export(
     ),
 ):
     """Export the app to a zip file."""
+    config = utils.get_config()
+
     if for_pc_deploy:
         # Get the app config and modify the api_url base on username and app_name.
-        config = utils.get_config()
         config.api_url = utils.get_production_backend_url()
 
     # Compile the app in production mode and export it.
     utils.console.rule("[bold]Compiling production app and preparing for export.")
     app = utils.get_app().app
-    utils.export_app(app, backend=backend, frontend=frontend, zip=zipping)
+    utils.export_app(
+        app,
+        backend=backend,
+        frontend=frontend,
+        zip=zipping,
+        deploy_url=config.deploy_url,
+    )
 
     # Post a telemetry event.
     pynecone_telemetry("export", utils.get_config().telemetry_enabled)

+ 30 - 1
pynecone/utils.py

@@ -493,8 +493,32 @@ def set_pynecone_project_hash():
         json.dump(pynecone_json, f, ensure_ascii=False)
 
 
+def generate_sitemap(deploy_url: str):
+    """Generate the sitemap config file.
+
+    Args:
+        deploy_url: The URL of the deployed app.
+    """
+    # Import here to avoid circular imports.
+    from pynecone.compiler import templates
+
+    config = json.dumps(
+        {
+            "siteUrl": deploy_url,
+            "generateRobotsTxt": True,
+        }
+    )
+
+    with open(constants.SITEMAP_CONFIG_FILE, "w") as f:
+        f.write(templates.SITEMAP_CONFIG(config=config))
+
+
 def export_app(
-    app: App, backend: bool = True, frontend: bool = True, zip: bool = False
+    app: App,
+    backend: bool = True,
+    frontend: bool = True,
+    zip: bool = False,
+    deploy_url: Optional[str] = None,
 ):
     """Zip up the app for deployment.
 
@@ -503,6 +527,7 @@ def export_app(
         backend: Whether to zip up the backend app.
         frontend: Whether to zip up the frontend app.
         zip: Whether to zip the app.
+        deploy_url: The URL of the deployed app.
     """
     # Force compile the app.
     app.compile(force_compile=True)
@@ -510,6 +535,10 @@ def export_app(
     # Remove the static folder.
     rm(constants.WEB_STATIC_DIR)
 
+    # Generate the sitemap file.
+    if deploy_url is not None:
+        generate_sitemap(deploy_url)
+
     # Export the Next app.
     subprocess.run([get_package_manager(), "run", "export"], cwd=constants.WEB_DIR)
 

+ 1 - 1
pyproject.toml

@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "pynecone"
-version = "0.1.14"
+version = "0.1.16"
 description = "Web apps in pure Python."
 license = "Apache-2.0"
 authors = [