├── .devcontainer ├── Dockerfile ├── devcontainer.json └── library-scripts │ └── node-debian.sh ├── .gitignore ├── package-lock.json ├── package.json ├── readme.md └── src ├── index.html └── styles.css /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # Find the Dockerfile at this URL 2 | # https://github.com/Azure/azure-functions-docker/blob/dev/host/4/bullseye/amd64/python/python39/python39-core-tools.Dockerfile 3 | FROM mcr.microsoft.com/azure-functions/python:4-python3.9-core-tools 4 | 5 | # Copy library scripts to execute 6 | COPY library-scripts/*.sh library-scripts/*.env /tmp/library-scripts/ 7 | 8 | # Install Node.js, Azure Static Web Apps CLI and Azure Functions Core Tools 9 | ARG NODE_VERSION="16" 10 | ARG CORE_TOOLS_VERSION="4" 11 | ENV NVM_DIR="/usr/local/share/nvm" \ 12 | NVM_SYMLINK_CURRENT=true \ 13 | PATH="${NVM_DIR}/current/bin:${PATH}" 14 | RUN bash /tmp/library-scripts/node-debian.sh "${NVM_DIR}" "${NODE_VERSION}" "${USERNAME}" \ 15 | && su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1" \ 16 | && su vscode -c "umask 0002 && npm install --cache /tmp/empty-cache -g @azure/static-web-apps-cli" \ 17 | && if [ $CORE_TOOLS_VERSION != "4" ]; then apt-get remove -y azure-functions-core-tools-4 && apt-get update && apt-get install -y "azure-functions-core-tools-${CORE_TOOLS_VERSION}"; fi \ 18 | && apt-get clean -y && rm -rf /var/lib/apt/lists/* 19 | 20 | # [Optional] Uncomment this section to install additional OS packages. 21 | # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 22 | # && apt-get -y install --no-install-recommends 23 | 24 | # [Optional] Uncomment this line to install global node packages. 25 | # RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 26 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.236.0/containers/azure-static-web-apps 3 | { 4 | "name": "Azure Static Web Apps - vanilla sample", 5 | "build": { 6 | "dockerfile": "Dockerfile", 7 | "args": { 8 | // Please look at runtime version support to make sure you're using compatible versions 9 | // https://docs.microsoft.com/en-us/azure/azure-functions/supported-languages#languages-by-runtime-version 10 | "NODE_VERSION": "16", 11 | "CORE_TOOLS_VERSION": "4" 12 | } 13 | }, 14 | "forwardPorts": [ 7071, 4280 ], 15 | 16 | // Configure tool-specific properties. 17 | "customizations": { 18 | // Configure properties specific to VS Code. 19 | "vscode": { 20 | // Add the IDs of extensions you want installed when the container is created. 21 | "extensions": [ 22 | "ms-azuretools.vscode-azurefunctions", 23 | "ms-azuretools.vscode-azurestaticwebapps", 24 | "ms-dotnettools.csharp", 25 | "ms-python.python", 26 | "dbaeumer.vscode-eslint" 27 | ] 28 | } 29 | }, 30 | 31 | // Use 'postCreateCommand' to run commands after the container is created. 32 | // "postCreateCommand": "node --version", 33 | 34 | // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. 35 | "remoteUser": "vscode" 36 | } 37 | -------------------------------------------------------------------------------- /.devcontainer/library-scripts/node-debian.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #------------------------------------------------------------------------------------------------------------- 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. 5 | #------------------------------------------------------------------------------------------------------------- 6 | # 7 | # Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/node.md 8 | # Maintainer: The VS Code and Codespaces Teams 9 | # 10 | # Syntax: ./node-debian.sh [directory to install nvm] [node version to install (use "none" to skip)] [non-root user] [Update rc files flag] [install node-gyp deps] 11 | 12 | export NVM_DIR=${1:-"/usr/local/share/nvm"} 13 | export NODE_VERSION=${2:-"lts"} 14 | USERNAME=${3:-"automatic"} 15 | UPDATE_RC=${4:-"true"} 16 | INSTALL_TOOLS_FOR_NODE_GYP="${5:-true}" 17 | export NVM_VERSION="0.38.0" 18 | 19 | set -e 20 | 21 | if [ "$(id -u)" -ne 0 ]; then 22 | echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' 23 | exit 1 24 | fi 25 | 26 | # Ensure that login shells get the correct path if the user updated the PATH using ENV. 27 | rm -f /etc/profile.d/00-restore-env.sh 28 | echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh 29 | chmod +x /etc/profile.d/00-restore-env.sh 30 | 31 | # Determine the appropriate non-root user 32 | if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then 33 | USERNAME="" 34 | POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)") 35 | for CURRENT_USER in ${POSSIBLE_USERS[@]}; do 36 | if id -u ${CURRENT_USER} > /dev/null 2>&1; then 37 | USERNAME=${CURRENT_USER} 38 | break 39 | fi 40 | done 41 | if [ "${USERNAME}" = "" ]; then 42 | USERNAME=root 43 | fi 44 | elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then 45 | USERNAME=root 46 | fi 47 | 48 | updaterc() { 49 | if [ "${UPDATE_RC}" = "true" ]; then 50 | echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..." 51 | if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then 52 | echo -e "$1" >> /etc/bash.bashrc 53 | fi 54 | if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then 55 | echo -e "$1" >> /etc/zsh/zshrc 56 | fi 57 | fi 58 | } 59 | 60 | # Function to run apt-get if needed 61 | apt_get_update_if_needed() 62 | { 63 | if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then 64 | echo "Running apt-get update..." 65 | apt-get update 66 | else 67 | echo "Skipping apt-get update." 68 | fi 69 | } 70 | 71 | # Checks if packages are installed and installs them if not 72 | check_packages() { 73 | if ! dpkg -s "$@" > /dev/null 2>&1; then 74 | apt_get_update_if_needed 75 | apt-get -y install --no-install-recommends "$@" 76 | fi 77 | } 78 | 79 | # Ensure apt is in non-interactive to avoid prompts 80 | export DEBIAN_FRONTEND=noninteractive 81 | 82 | # Install dependencies 83 | check_packages apt-transport-https curl ca-certificates tar gnupg2 dirmngr 84 | 85 | # Install yarn 86 | if type yarn > /dev/null 2>&1; then 87 | echo "Yarn already installed." 88 | else 89 | # Import key safely (new method rather than deprecated apt-key approach) and install 90 | curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor > /usr/share/keyrings/yarn-archive-keyring.gpg 91 | echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/yarn-archive-keyring.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list 92 | apt-get update 93 | apt-get -y install --no-install-recommends yarn 94 | fi 95 | 96 | # Adjust node version if required 97 | if [ "${NODE_VERSION}" = "none" ]; then 98 | export NODE_VERSION= 99 | elif [ "${NODE_VERSION}" = "lts" ]; then 100 | export NODE_VERSION="lts/*" 101 | fi 102 | 103 | # Create a symlink to the installed version for use in Dockerfile PATH statements 104 | export NVM_SYMLINK_CURRENT=true 105 | 106 | # Install the specified node version if NVM directory already exists, then exit 107 | if [ -d "${NVM_DIR}" ]; then 108 | echo "NVM already installed." 109 | if [ "${NODE_VERSION}" != "" ]; then 110 | su ${USERNAME} -c ". $NVM_DIR/nvm.sh && nvm install ${NODE_VERSION} && nvm clear-cache" 111 | fi 112 | exit 0 113 | fi 114 | 115 | # Create nvm group, nvm dir, and set sticky bit 116 | if ! cat /etc/group | grep -e "^nvm:" > /dev/null 2>&1; then 117 | groupadd -r nvm 118 | fi 119 | umask 0002 120 | usermod -a -G nvm ${USERNAME} 121 | mkdir -p ${NVM_DIR} 122 | chown :nvm ${NVM_DIR} 123 | chmod g+s ${NVM_DIR} 124 | su ${USERNAME} -c "$(cat << EOF 125 | set -e 126 | umask 0002 127 | # Do not update profile - we'll do this manually 128 | export PROFILE=/dev/null 129 | ls -lah /home/${USERNAME}/.nvs || : 130 | curl -so- https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh | bash 131 | source ${NVM_DIR}/nvm.sh 132 | if [ "${NODE_VERSION}" != "" ]; then 133 | nvm alias default ${NODE_VERSION} 134 | fi 135 | nvm clear-cache 136 | EOF 137 | )" 2>&1 138 | # Update rc files 139 | if [ "${UPDATE_RC}" = "true" ]; then 140 | updaterc "$(cat < /dev/null 2>&1; then 153 | to_install="${to_install} make" 154 | fi 155 | if ! type gcc > /dev/null 2>&1; then 156 | to_install="${to_install} gcc" 157 | fi 158 | if ! type g++ > /dev/null 2>&1; then 159 | to_install="${to_install} g++" 160 | fi 161 | if ! type python3 > /dev/null 2>&1; then 162 | to_install="${to_install} python3-minimal" 163 | fi 164 | if [ ! -z "${to_install}" ]; then 165 | apt_get_update_if_needed 166 | apt-get -y install ${to_install} 167 | fi 168 | fi 169 | 170 | echo "Done!" 171 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | /test-results/ 3 | 4 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vanilla-basic", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "vanilla-basic", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "@playwright/test": "^1.22.2" 13 | } 14 | }, 15 | "node_modules/@playwright/test": { 16 | "version": "1.22.2", 17 | "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.22.2.tgz", 18 | "integrity": "sha512-cCl96BEBGPtptFz7C2FOSN3PrTnJ3rPpENe+gYCMx4GNNDlN4tmo2D89y13feGKTMMAIVrXfSQ/UmaQKLy1XLA==", 19 | "dev": true, 20 | "dependencies": { 21 | "@types/node": "*", 22 | "playwright-core": "1.22.2" 23 | }, 24 | "bin": { 25 | "playwright": "cli.js" 26 | }, 27 | "engines": { 28 | "node": ">=14" 29 | } 30 | }, 31 | "node_modules/@types/node": { 32 | "version": "18.0.0", 33 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz", 34 | "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==", 35 | "dev": true 36 | }, 37 | "node_modules/playwright-core": { 38 | "version": "1.22.2", 39 | "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.22.2.tgz", 40 | "integrity": "sha512-w/hc/Ld0RM4pmsNeE6aL/fPNWw8BWit2tg+TfqJ3+p59c6s3B6C8mXvXrIPmfQEobkcFDc+4KirNzOQ+uBSP1Q==", 41 | "dev": true, 42 | "bin": { 43 | "playwright": "cli.js" 44 | }, 45 | "engines": { 46 | "node": ">=14" 47 | } 48 | } 49 | }, 50 | "dependencies": { 51 | "@playwright/test": { 52 | "version": "1.22.2", 53 | "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.22.2.tgz", 54 | "integrity": "sha512-cCl96BEBGPtptFz7C2FOSN3PrTnJ3rPpENe+gYCMx4GNNDlN4tmo2D89y13feGKTMMAIVrXfSQ/UmaQKLy1XLA==", 55 | "dev": true, 56 | "requires": { 57 | "@types/node": "*", 58 | "playwright-core": "1.22.2" 59 | } 60 | }, 61 | "@types/node": { 62 | "version": "18.0.0", 63 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz", 64 | "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==", 65 | "dev": true 66 | }, 67 | "playwright-core": { 68 | "version": "1.22.2", 69 | "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.22.2.tgz", 70 | "integrity": "sha512-w/hc/Ld0RM4pmsNeE6aL/fPNWw8BWit2tg+TfqJ3+p59c6s3B6C8mXvXrIPmfQEobkcFDc+4KirNzOQ+uBSP1Q==", 71 | "dev": true 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vanilla-basic", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "start": "sirv ./src public --cors --single --no-clear --port 8000" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Vanilla JavaScript App 2 | 3 | [Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/overview) allows you to easily build JavaScript apps in minutes. Use this repo with the [quickstart](https://docs.microsoft.com/azure/static-web-apps/getting-started?tabs=vanilla-javascript) to build and customize a new static site. 4 | 5 | This repo is used as a starter for a _very basic_ HTML web application using no front-end frameworks. 6 | 7 | This repo has a dev container. This means if you open it inside a [GitHub Codespace](https://github.com/features/codespaces), or using [VS Code with the remote containers extension](https://code.visualstudio.com/docs/remote/containers), it will be opened inside a container with all the dependencies already installed. -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Vanilla JavaScript App 9 | 10 | 11 | 12 |
13 |

Vanilla JavaScript App

14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: Arial, Helvetica, sans-serif; 3 | } 4 | 5 | html, body { 6 | margin: 0; 7 | border: 0; 8 | padding: 0; 9 | background-color: #fff; 10 | } 11 | 12 | main { 13 | margin: auto; 14 | width: 50%; 15 | padding: 20px; 16 | } 17 | 18 | main > h1 { 19 | text-align: center; 20 | font-size: 3.5em; 21 | } --------------------------------------------------------------------------------