Skip to main content

Quick Start Guide

This guide walks you through building and serving your first pre-rendered Angular application with Scully. In just a few minutes, you’ll see your Angular app transformed into lightning-fast static pages.

Prerequisites

Before starting, ensure you have:
  • Completed the Installation steps
  • An Angular project with at least one route configured
  • Node.js 12 or higher installed

Step-by-Step Guide

Step 1: Build Your Angular Application

Before Scully can pre-render your app, you need to build it:
ng build
This command compiles your Angular application and outputs the build artifacts to the dist/ directory.
For production builds, use ng build --configuration production to enable optimizations like minification and tree-shaking.

Step 2: Run Scully

Now run Scully to pre-render your application:
npx scully
What’s happening? Scully is:
  1. Loading your Scully configuration
  2. Discovering all routes in your Angular app
  3. Launching a headless browser to render each route
  4. Saving the rendered HTML to static files
You’ll see output similar to this:
 Scully found 5 routes to process
 Analyzing routes...
 Rendering routes...
 Rendering 5 pages...
 Scully rendered 5 pages in 12.5s

Step 3: View the Static Files

Scully generates static HTML files in the ./dist/static directory:
ls dist/static
You’ll see an index.html file for each route in your application. If your app has 10 routes, you’ll find 10 HTML files.
dist/static/
├── index.html              # Root route
├── about/
   └── index.html         # /about route
├── blog/
   └── index.html         # /blog route
└── contact/
    └── index.html         # /contact route

Step 4: Serve Your Static Site

Scully includes a built-in server to preview your pre-rendered site:
npx scully serve
This command launches two servers:

Angular Build

http://localhost:4200Your standard Angular build (from ng build)

Static Build

http://localhost:1668Your Scully pre-rendered static site

Step 5: Compare Performance

Open both URLs in your browser and compare:
1

Test Angular Build

Visit http://localhost:4200 and watch the network tab. You’ll see the full Angular app download and bootstrap.
2

Test Static Build

Visit http://localhost:1668 and watch the network tab. The page appears instantly with pre-rendered content.
3

Check Page Source

Right-click and “View Page Source” on both. The static build shows full HTML content, while the Angular build shows minimal HTML.
Success! You’ve successfully pre-rendered your Angular application with Scully.

Understanding the Output

Static Files

Each route in your app becomes a static HTML file:
index.html example
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>My App</title>
  <!-- All your meta tags, styles, etc. -->
</head>
<body>
  <app-root>
    <!-- Fully rendered content is here! -->
    <h1>Welcome to My App</h1>
    <p>This content loads instantly...</p>
  </app-root>
  <!-- Angular scripts load after content is visible -->
  <script src="runtime.js" type="module"></script>
  <script src="polyfills.js" type="module"></script>
  <script src="main.js" type="module"></script>
</body>
</html>

Routes Configuration

Scully also generates a scully-routes.json file containing all discovered routes:
scully-routes.json
[
  {
    "route": "/",
    "sourceFile": "./src/app/home/home.component.ts"
  },
  {
    "route": "/about",
    "sourceFile": "./src/app/about/about.component.ts"
  }
]

Common Workflows

Development Workflow

During development, rebuild your app and re-run Scully when you make changes:
# Make changes to your Angular app
# Then rebuild and re-render
ng build && npx scully
Use npx scully --watch to automatically re-render when files change during development.

Production Workflow

For production builds:
# Build for production
ng build --configuration production

# Run Scully
npx scully --scanRoutes

# Deploy the dist/static folder
The dist/static folder contains everything you need to deploy - just upload it to any static hosting provider.

Deployment

Deploy your static site to any hosting provider that serves static files:

Netlify

# netlify.toml
[build]
  publish = "dist/static"
  command = "ng build --configuration production && npx scully"

Vercel

# vercel.json
{
  "buildCommand": "ng build --configuration production && npx scully",
  "outputDirectory": "dist/static"
}

AWS S3

# Upload static files
aws s3 sync dist/static s3://your-bucket-name

GitHub Pages

# Deploy to gh-pages branch
npx angular-cli-ghpages --dir=dist/static

Handling Route Parameters

If your app has routes with parameters (like /blog/:slug or /user/:id), Scully needs additional configuration.
Routes with parameters will show this warning:
No configuration for route '/user/:userId' found. Skipping
Configure parameterized routes in your scully.config.ts:
scully.config.ts
import { ScullyConfig } from '@scullyio/scully';

export const config: ScullyConfig = {
  projectRoot: './src',
  projectName: 'my-app',
  outDir: './dist/static',
  routes: {
    '/blog/:slug': {
      type: 'contentFolder',
      slug: {
        folder: './blog'
      }
    },
    '/user/:userId': {
      type: 'json',
      userId: {
        url: 'https://api.example.com/users',
        property: 'id'
      }
    }
  }
};
Learn more about configuring routes with parameters in the Route Configuration guide.

Troubleshooting

Problem: Scully can’t discover any routes in your app.Solutions:
  • Verify your Angular app has routes configured
  • Check that you ran ng build before npx scully
  • Ensure your router module is properly imported
  • Try adding routes manually via extraRoutes in the config
Problem: Static HTML files are empty or missing content.Solutions:
  • Check browser console for JavaScript errors
  • Verify all async data loads complete before rendering
  • Use scully-routes service to detect when Scully is running
  • Increase render timeout in Scully config
Problem: Parameterized routes show “No configuration found” warning.Solutions:
  • Add route configuration to the routes object in your Scully config
  • Use the json plugin for API-based routes
  • Use the contentFolder plugin for file-based routes (like blogs)
  • See Route Configuration for examples
Problem: Scully gets stuck and never completes.Solutions:
  • Check for infinite loops or long-running timers in your components
  • Use manualIdleCheck for routes that need manual completion signals
  • Increase the puppeteerLaunchOptions.timeout value
  • Check for console errors in the rendered pages

Next Steps

Now that you’ve built your first static Angular app with Scully, explore these topics:

Create a Blog

Learn how to add a blog to your site with Markdown support

Plugin System

Extend Scully with custom plugins for advanced functionality

Configuration

Explore all configuration options for fine-tuning Scully

Best Practices

Learn tips and best practices for testing and optimization

Get Help

Need assistance? The Scully community is here to help:
Congratulations! You’ve successfully created your first pre-rendered Angular application with Scully. Your app now loads instantly and is fully SEO-optimized.

Build docs developers (and LLMs) love