diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..0f7c283 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,50 @@ +{ + "name": "Debian", + "image": "mcr.microsoft.com/devcontainers/base:bullseye", + "features": { + "ghcr.io/devcontainers/features/node:1": {}, + "ghcr.io/devcontainers/features/docker-in-docker:2": {}, + "ghcr.io/devcontainers/features/github-cli:1": {} + }, + "forwardPorts": [ + 4321 + ], + "secrets": {}, + "remoteEnv": { + "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}" + }, + "customizations": { + "vscode": { + "extensions": [ + "eamodio.gitlens", + "github.copilot", + "github.copilot-chat", + "github.vscode-github-actions", + "ms-vscode.makefile-tools", + "astro-build.astro-vscode", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "bradlc.vscode-tailwindcss" + ], + "settings": { + "terminal.integrated.defaultProfile.linux": "zsh" + }, + "mcp": { + "servers": { + "playwright": { + "command": "npx", + "args": [ + "@playwright/mcp@latest" + ] + }, + "lighthouse": { + "command": "npx", + "args": [ + "lighthouse-mcp" + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c7f525f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM ghcr.io/super-linter/super-linter:slim-v8.0.0 + +HEALTHCHECK --interval=5m --timeout=10s --start-period=30s --retries=3 CMD ["/bin/sh","-c","test -d /github/home"] +ARG UID=1000 +ARG GID=1000 +RUN chown -R ${UID}:${GID} /github/home +USER ${UID}:${GID} + +ENV RUN_LOCAL=true +ENV USE_FIND_ALGORITHM=false +ENV IGNORE_GITIGNORED_FILES=true +ENV LOG_LEVEL=WARN +ENV LOG_FILE="/github/home/logs" +ENV DEFAULT_BRANCH=main \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..986f1c5 --- /dev/null +++ b/Makefile @@ -0,0 +1,88 @@ +.PHONY: help + +MAKEFLAGS += --silent +.DEFAULT_GOAL := help + +help: ## Show help message + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[$$()% a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +include .env + +setup: ## Prepare stack to run + cd application && npm install + cd .github/actions/generate-blog-post && npm install + cd .github/actions/generate-brand-content && npm install + cd .github/actions/validate-manifest && npm install + +start: ## Start application in dev mode + cd application && npm run start + +lint: ## Run linters + cd application && npm run lint -- $(filter-out $@,$(MAKECMDGOALS)) + $(call run_linter,) + +lint-fix: ## Run linters + cd application && npm audit --omit=dev + cd application && npm run humanize:fix + cd application && npm run lint:fix + $(MAKE) linter-fix + +build: ## Build libs and applications + cd application && npm run build + +test: ## Run tests + cd application && npm run test:ci + cd .github/actions/generate-blog-post && npm run test:ci + cd .github/actions/generate-brand-content && npm run test:ci + cd .github/actions/validate-manifest && npm run test:ci + +ci: ## Run tests in CI mode + $(MAKE) lint-fix + $(MAKE) build + $(MAKE) test + +linter-fix: ## Execute linting and fix + $(call run_linter, \ + -e FIX_CSS_PRETTIER=true \ + -e FIX_JSON_PRETTIER=true \ + -e FIX_JAVASCRIPT_PRETTIER=true \ + -e FIX_YAML_PRETTIER=true \ + -e FIX_MARKDOWN=true \ + -e FIX_MARKDOWN_PRETTIER=true \ + -e FIX_NATURAL_LANGUAGE=true) + +define run_linter + DEFAULT_WORKSPACE="$(CURDIR)"; \ + LINTER_IMAGE="linter:latest"; \ + VOLUME="$$DEFAULT_WORKSPACE:$$DEFAULT_WORKSPACE"; \ + docker build --build-arg UID=$(shell id -u) --build-arg GID=$(shell id -g) --tag $$LINTER_IMAGE .; \ + docker run \ + -v $$VOLUME \ + --rm \ + -w "$$DEFAULT_WORKSPACE" \ + -e DEFAULT_WORKSPACE="$$DEFAULT_WORKSPACE" \ + -e GITHUB_WORKSPACE="$$DEFAULT_WORKSPACE" \ + -e FILTER_REGEX_INCLUDE="$(filter-out $@,$(MAKECMDGOALS))" \ + -e VALIDATE_TYPESCRIPT_PRETTIER=false \ + -e VALIDATE_TYPESCRIPT_ES=false \ + -e VALIDATE_CSS=false \ + $(1) \ + $$LINTER_IMAGE +endef + +define docker-compose + COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f docker-compose.yml -f docker-compose.local.yml -f docker-compose.$(1).yml $(2) +endef + +define open-in-browser + @if command -v x-www-browser &> /dev/null ; then x-www-browser $(1); \ + elif command -v xdg-open &> /dev/null ; then xdg-open $(1); \ + elif command -v open &> /dev/null ; then open $(1); \ + elif command -v start &> /dev/null ; then start $(1); fi; +endef + +############################# +# Argument fix workaround +############################# +%: + @: diff --git a/README.md b/README.md index d2660c8..01b0501 100644 --- a/README.md +++ b/README.md @@ -1,179 +1,119 @@ -# Cloud Native Provence - Landing page +# Cloud Native Provence — Landing Page -### Project structure +Astro-based conference website with bilingual routing (`fr` / `en`) and translated slugs. +## Development workflow (Makefile-first) + +Use `make` commands from the repository root. + +```bash +make help ``` -/ -└── application/ - ├── public/ - │ ├── _headers - │ └── robots.txt - ├── src/ - │ ├── assets/ - │ │ ├── favicons/ - │ │ ├── images/ - │ │ └── styles/ - │ │ └── tailwind.css - │ ├── components/ - │ │ ├── blog/ - │ │ ├── common/ - │ │ ├── ui/ - │ │ ├── widgets/ - │ │ │ ├── Header.astro - │ │ │ └── ... - │ │ ├── CustomStyles.astro - │ │ ├── Favicons.astro - │ │ └── Logo.astro - │ ├── content/ - │ │ ├── post/ - │ │ │ ├── post-slug-1.md - │ │ │ ├── post-slug-2.mdx - │ │ │ └── ... - │ │ └-- config.ts - │ ├── layouts/ - │ │ ├── Layout.astro - │ │ ├── MarkdownLayout.astro - │ │ └── PageLayout.astro - │ ├── pages/ - │ │ ├── [...blog]/ - │ │ │ ├── [category]/ - │ │ │ ├── [tag]/ - │ │ │ ├── [...page].astro - │ │ │ └── index.astro - │ │ ├── index.astro - │ │ ├── 404.astro - │ │ ├-- rss.xml.ts - │ │ └── ... - │ ├── utils/ - │ ├── config.yaml - │ └── navigation.js - ├── package.json - ├── astro.config.ts - └── ... -``` -Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. - -There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. - -Any static assets, like images, can be placed in the `public/` directory if they do not require any transformation or in the `assets/` directory if they are imported directly. - -
- -### Commands - -All commands are run from the `application` folder, from a terminal: - -| Command | Action | -| :------------------ | :------------------------------------------------- | -| `npm install` | Installs dependencies | -| `npm run dev` | Starts local dev server at `localhost:4321` | -| `npm run build` | Build your production site to `./dist/` | -| `npm run preview` | Preview your build locally, before deploying | -| `npm run check` | Check your project for errors | -| `npm run fix` | Run Eslint and format codes with Prettier | -| `npm run astro ...` | Run CLI commands like `astro add`, `astro preview` | - -
- -### Configuration - -Basic configuration file: `./src/config.yaml` - -```yaml -site: - name: "Example" - site: "https://example.com" - base: "/" # Change this if you need to deploy to Github Pages, for example - trailingSlash: false # Generate permalinks with or without "/" at the end - - googleSiteVerificationId: false # Or some value, - -# Default SEO metadata -metadata: - title: - default: "Example" - template: "%s — Example" - description: "This is the default meta description of Example website" - robots: - index: true - follow: true - openGraph: - site_name: "Example" - images: - - url: "~/assets/images/default.png" - width: 1200 - height: 628 - type: website - twitter: - handle: "@twitter_user" - site: "@twitter_user" - cardType: summary_large_image - -i18n: - language: en - textDirection: ltr - -apps: - blog: - isEnabled: true # If the blog will be enabled - postsPerPage: 6 # Number of posts per page - - post: - isEnabled: true - permalink: "/blog/%slug%" # Variables: %slug%, %year%, %month%, %day%, %hour%, %minute%, %second%, %category% - robots: - index: true - - list: - isEnabled: true - pathname: "blog" # Blog main path, you can change this to "articles" (/articles) - robots: - index: true - - category: - isEnabled: true - pathname: "category" # Category main path /category/some-category, you can change this to "group" (/group/some-category) - robots: - index: true - - tag: - isEnabled: true - pathname: "tag" # Tag main path /tag/some-tag, you can change this to "topics" (/topics/some-category) - robots: - index: false - - isRelatedPostsEnabled: true # If a widget with related posts is to be displayed below each post - relatedPostsCount: 4 # Number of related posts to display - -analytics: - vendors: - googleAnalytics: - id: null # or "G-XXXXXXXXXX" - -ui: - theme: "system" # Values: "system" | "light" | "dark" | "light:only" | "dark:only" +Main targets: + +- `make setup` — install project dependencies +- `make start` — start local dev server (`application`) +- `make build` — production build +- `make lint` — run linters/checks +- `make lint-fix` — run fixers +- `make ci` — lint + build + test pipeline + +Do not run `npm run ...` directly unless you are explicitly debugging Makefile behavior. + +## Dev Container + +This repository includes a VS Code Dev Container in `.devcontainer/devcontainer.json`. + +### Recommended usage + +1. Open the repository in VS Code. +2. Run `Dev Containers: Reopen in Container`. +3. Once inside the container, run: + +```bash +make setup +make start ``` -
+The dev container provides: -#### Customize Design +- Node.js +- Docker-in-Docker +- GitHub CLI +- VS Code extensions for Astro, ESLint, Prettier, Tailwind, Makefile, Copilot -To customize Font families, Colors or more Elements refer to the following files: +The app is available on port `4321`. -- `src/components/CustomStyles.astro` -- `src/assets/styles/tailwind.css` +## Current routing model -### Deploy +Routing is locale-first and centralized. -#### Deploy to production (manual) +- `/` redirects to `/fr` +- `/fr` and `/en` are localized homepages +- `/{lang}/{translated-slug}` for content pages -You can create an optimized production build with: +Key files: -```shell -npm run build +- `application/src/pages/index.astro` — root redirect +- `application/src/pages/[lang]/index.astro` — localized homepage +- `application/src/pages/[lang]/[page].astro` — localized dynamic pages +- `application/src/i18n/routes.ts` — route slug mapping + path helpers + +Example translated slugs: + +- FR: `/fr/a-propos`, `/fr/charte-graphique`, `/fr/politique-de-confidentialite` +- EN: `/en/about`, `/en/brand-guidelines`, `/en/privacy-policy` + +## Project structure (current) + +```text +/ +├── .devcontainer/ +├── Makefile +├── Dockerfile +├── README.md +└── application/ + ├── astro.config.ts + ├── package.json + ├── public/ + │ ├── _headers + │ ├── robots.txt + │ └── .well-known/appspecific/com.chrome.devtools.json + └── src/ + ├── assets/ + ├── components/ + ├── i18n/ + │ ├── ui.ts + │ ├── utils.ts + │ └── routes.ts + ├── layouts/ + ├── pages/ + │ ├── [lang]/ + │ │ ├── index.astro + │ │ └── [page].astro + │ ├── [...blog]/ + │ ├── home/ + │ ├── about/ + │ ├── contact/ + │ ├── sponsoring/ + │ ├── brand-guidelines/ + │ ├── terms/ + │ ├── privacy/ + │ ├── index.astro + │ ├── rss.xml.ts + │ └── 404.astro + └── utils/ ``` -Now, your website is ready to be deployed. All generated files are located at -`dist` folder, which you can deploy the folder to any hosting service you -prefer. +## Configuration + +Primary site configuration: `application/src/config.yaml`. + +Astro framework configuration: `application/astro.config.ts`. + +## Build output + +Production build output is generated in: + +- `application/dist/`