Setting up a new project + Linters/Formatters
Setting up a new project + Linters/Formatters
SvelteKit
Default prject structure:
<app-name>/
├─ eslint.config.mjs
├─ prettier.config.mjs
├─ .prettierignore
├─ package.json
└─ src/Setting up linter and formatter (ESLint and Prettier):
Install dev packages
npm install --save-dev eslint prettier eslint-config-prettier \
@eslint/js @eslint/eslintrc eslint-plugin-svelte svelte-eslint-parser \
@typescript-eslint/parser @typescript-eslint/eslint-pluginSet up config files (copy from below)
eslint.config.mjs
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";
import pluginSvelte from "eslint-plugin-svelte";
import prettierConfig from "eslint-config-prettier";
const __filename = fileURLToPath(import.meta.url);
const dirname = dirname(filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
});
const eslintConfig = [
...compat.extends(
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
),
prettierConfig,
{
files: ["**/*.svelte"],
plugins: { svelte: pluginSvelte },
languageOptions: {
parser: pluginSvelte.parsers["svelte-eslint-parser"],
parserOptions: {
parser: "@typescript-eslint/parser",
extraFileExtensions: [".svelte"],
},
},
rules: {
"svelte/no-at-html-tags": "error",
"svelte/no-ignored-svelte-ignore": "warn",
},
},
{
ignores: [
"node_modules/**",
".svelte-kit/**",
"build/**",
"dist/**",
"static/**",
"coverage/**",
"vite.config.*",
"svelte.config.*",
],
rules: {
"no-console": "warn",
"no-debugger": "error",
eqeqeq: ["error", "always"],
"no-var": "error",
"prefer-const": "warn",
"prefer-arrow-callback": "warn",
},
},
];
export default eslintConfig;prettier.config.mjs
Defaults are commented out.
/** @type {import("prettier").Config} */
const config = {
// semi: true,
// trailingComma: "all",
// singleQuote: false,
// printWidth: 80,
// tabWidth: 2,
// useTabs: false,
// endOfLine: "lf",
};
export default config;.prettierignore
# Dependencies
node_modules/
.next/
out/
build/
dist/
public/
# Production
*.min.js
*.min.css
# Environment variables
.env
.env*.local
# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# IDE
.vscode/
.idea/
# OS
.DS_Store
Thumbs.db
# Coverage
coverage/
*.lcov
# Misc
.nextflow/
*.swp
*.swoUpdate package.json:
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --check .",
"format:fix": "prettier --write ."
}Usage: (TODO: add to mise)
//Check for ESLint errors
npm run lint
//Fix fixable ESLint issues
npm run lint:fix
//Check code formatting
npm run format
//Format code automatically
npm run format:fixFastAPI (Python)
Default prject structure:
<app-name>/
├─ pyproject.toml
├─ mise.toml
├─ docker-compose.yml
└─ src/Setting up the project
Install mise
Install uv
Recommended language server: ty
mise initAdd to
mise.toml:[env] UV_PROJECT_ENVIRONMENT = ".venv"mise use <tool>@<version>uv initUpdate
pypropject.tomlwith Ruff configuration like this:... [tool.ruff] exclude = [".venv"] [tool.ruff.lint] select = ["ALL"] ignore = [ # Rules to ignore, if any ] [tool.ruff.lint.pydocstyle] convention = "google"uv add <package> --group devfor development/test-only oruv add <package>for production.Follow the documentation to configure mise tasks. See example:
[tasks.db] description = "Starts the DB through docker compose" run = "docker compose up -d mongodb" [tasks.dev] description = "Run FastAPI in development mode." depends = ["db"] run = "uv run unicorn src.main:app" run_windows = "uv run unicorn src.main:app" [tasks.compose] description = "Run FastAPI via self-sufficient docker compose config" run = "docker compose up -d"Recommended: define
docker-compose.ymlwith the necessary services for your project. See example:name: april-robots-online-general-api services: app: build: context: . dockerfile: .docker/dev/Dockerfile args: WORKDIR: /app environment: # Override MONGOHOST and KEYCLOAK_SERVER_URL # because containers are within one network MONGOHOST: mongodb KEYCLOAK_SERVER_URL: "http://keycloak:8080/" # Override default wait_and_start.sh args KC_HOST: keycloak HOST: 0.0.0.0 volumes: # Why not just `.:/app`? Because it messes up ./.venv - ./app:/app/app - ./database:/app/database - ./scripts:/app/scripts - ./tests:/app/tests - ./static:/app/static - ./version_maps:/app/version_maps - ./wait_and_start.sh:/app/wait_and_start.sh ports: - "8000:8000" networks: - april-hub depends_on: - mongodb healthcheck: test: ["CMD", "curl", "-f", "http://0.0.0.0:8000"] interval: 5s timeout: 5s retries: 3 start_period: 3s # This script ensures Keycloak has time to boot # before starting uvicorn command: ["./wait_and_start.sh"] mongodb: image: mongo:8.0.12-noble environment: MONGO_INITDB_ROOT_USERNAME: ${MONGOUSER:-root} MONGO_INITDB_ROOT_PASSWORD: ${MONGOPASSWORD:-password} ports: - "27017:27017" volumes: - mongodb_data:/data/db networks: - april-hub mongo-express: image: mongo-express:1.0.2 ports: - "8081:8081" environment: ME_CONFIG_BASICAUTH_USERNAME: admin ME_CONFIG_BASICAUTH_PASSWORD: admin ME_CONFIG_MONGODB_URL: mongodb://${MONGOUSER:-root}:${MONGOPASSWORD:-password}@mongodb:27017/ depends_on: - mongodb networks: - april-hub volumes: mongodb_data: networks: april-hub: name: april-hub-networkWrite Dockerfiles for development and production in
.docker/dev/Dockerfileor.docker/production/Dockerfile, correspondingly. See example:FROM python:3.12-slim ARG WORKDIR="/app" WORKDIR ${WORKDIR} RUN pip install --no-cache-dir uv COPY pyproject.toml uv.lock ./ RUN uv sync --no-dev COPY . . # Use uv to run inside the managed environment CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Setting up the IDE
See Quickstart