diff --git a/app/api_types.ts b/app/api_types.ts
index 46c1901c3b20bae5bf71126e673ad6e615d37e55..2def0dd7b8b3dd2eb34e5e4ba1f7f9f4f1d15e87 100644
--- a/app/api_types.ts
+++ b/app/api_types.ts
@@ -1,77 +1,77 @@
-export type ApiProjectId = number;
+export type ApiProjectId = number
 
 export type ApiLink = {
-  href: string;
-  rel: string;
-};
+  href: string
+  rel: string
+}
 
 export type ApiPicture = {
-  links: Array<ApiLink>;
-};
+  links: Array<ApiLink>
+}
 
 export type ApiCarrier = {
-  id: number;
-  name: string;
-  city: string | undefined | null;
-  country: string | undefined | null;
-  links: Array<ApiLink>;
-  picture: ApiPicture;
-};
+  id: number
+  name: string
+  city: string | undefined | null
+  country: string | undefined | null
+  links: Array<ApiLink>
+  picture: ApiPicture
+}
 
 /** only covers the parts of the API response type that were using */
 export type ApiProject = {
-  id: ApiProjectId;
-  title: string;
-  city: string | undefined | null;
-  country: string | undefined | null;
-  links: Array<ApiLink>;
-  carrier: ApiCarrier;
-  donations_count: number;
-  progress_percentage: number;
-  open_amount_in_cents: number;
-  profile_picture: ApiPicture | undefined;
-  summary: string | undefined | null;
-  description: string | undefined | null;
-  blog_post_count: number;
-};
+  id: ApiProjectId
+  title: string
+  city: string | undefined | null
+  country: string | undefined | null
+  links: Array<ApiLink>
+  carrier: ApiCarrier
+  donations_count: number
+  progress_percentage: number
+  open_amount_in_cents: number
+  profile_picture: ApiPicture | undefined
+  summary: string | undefined | null
+  description: string | undefined | null
+  blog_post_count: number
+}
 
 /** only covers the parts of the API response type that were using */
 export type ApiProjectsResponse = {
-  total_entries: number;
-  offset: number;
-  data: Array<ApiProject>;
-};
+  total_entries: number
+  offset: number
+  data: Array<ApiProject>
+}
 
-export type ApiProjectCategorySlug = string;
+export type ApiProjectCategorySlug = string
 
 export type ApiProjectCategory = {
-  created_at: string; // ISO datetime
-  id: number;
-  links: Array<ApiLink>;
-  name: string;
-  slug: ApiProjectCategorySlug;
-  updated_at: string; // ISO datetime
-};
+  created_at: string // ISO datetime
+  id: number
+  links: Array<ApiLink>
+  name: string
+  slug: ApiProjectCategorySlug
+  updated_at: string // ISO datetime
+}
 
 type ApiAuthor = {
-  name: string;
-  picture: ApiPicture;
-};
+  name: string
+  picture: ApiPicture
+}
 
 export type ApiBlogPost = {
-  id: number;
-  title: string;
-  published_at: string;
-  author?: ApiAuthor;
-  body: string;
-  links: Array<ApiLink>;
-};
+  id: number
+  title: string
+  published_at: string
+  author?: ApiAuthor
+  body: string
+  links: Array<ApiLink>
+}
 
 export type ApiBlogPostResponse = {
-  total_entries: number;
-  data: ApiBlogPost[];
-};
+  total_entries: number
+  data: ApiBlogPost[]
+}
 
 export type ApiOrganisation = {
-  links: Array<ApiLink>;
-};
+  links: Array<ApiLink>
+}
diff --git a/app/betterplace.ts b/app/betterplace.ts
index edb72c7aa73aca6ce4ace4f95f5f93b54e67fd5e..189edf31c5e8f38906309a0f1f6fe2d4d0b48e8e 100644
--- a/app/betterplace.ts
+++ b/app/betterplace.ts
@@ -1,4 +1,4 @@
-import { Parser } from "./deps.ts";
+import { Parser } from './deps.ts'
 import {
   BetterPlaceLanguage,
   Initiative,
@@ -9,7 +9,7 @@ import {
   ProjectParameters,
   ProjectsParameters,
   ProjectsResponse,
-} from "./types.ts";
+} from './types.ts'
 import {
   ApiBlogPost,
   ApiCarrier,
@@ -19,61 +19,61 @@ import {
   ApiProject,
   ApiProjectCategory,
   ApiProjectsResponse,
-} from "./api_types.ts";
-import { logger } from "./logging.ts";
-import { GraphQLError } from "./deps.ts";
+} from './api_types.ts'
+import { logger } from './logging.ts'
+import { GraphQLError } from './deps.ts'
 
-const BASE_URL = "https://api.betterplace.org";
-const PICTURE_TYPE_REGEX = /(.*)_(\d+)x(\d+)/;
-export const SUPPORTED_LANGUAGES = ["en", "de"];
-export const DEFAULT_LANGUAGE: BetterPlaceLanguage = "en";
-const DEFAULT_PAGE_SIZE = 10;
-const MAX_PAGE_FOR_RANDOMIZATION = 10;
-const ERROR_CODE_NOT_FOUND = "NOT_FOUND";
+const BASE_URL = 'https://api.betterplace.org'
+const PICTURE_TYPE_REGEX = /(.*)_(\d+)x(\d+)/
+export const SUPPORTED_LANGUAGES = ['en', 'de']
+export const DEFAULT_LANGUAGE: BetterPlaceLanguage = 'en'
+const DEFAULT_PAGE_SIZE = 10
+const MAX_PAGE_FOR_RANDOMIZATION = 10
+const ERROR_CODE_NOT_FOUND = 'NOT_FOUND'
 
 const cleanUpHtml = (html: string): string => {
-  let result = "";
+  let result = ''
   const parser = new Parser({
     onopentag: (name) => {
-      if (name === "br") {
-        result += "\n";
+      if (name === 'br') {
+        result += '\n'
       }
     },
     ontext: (text) => {
-      result += text;
+      result += text
     },
-  });
-  parser.end(html);
-  return result;
-};
+  })
+  parser.end(html)
+  return result
+}
 
 const transformPicture = (picture: ApiPicture | undefined): Picture[] => {
   if (!picture) {
-    return [];
+    return []
   }
   return picture.links.map((link: ApiLink) => {
     try {
-      const matches = PICTURE_TYPE_REGEX.exec(link.rel);
+      const matches = PICTURE_TYPE_REGEX.exec(link.rel)
       if (matches?.length !== 4) {
         return {
           type: link.rel,
           url: link.href,
-        };
+        }
       }
       return {
         type: matches[1],
         url: link.href,
         width: parseInt(matches[2], 10),
         height: parseInt(matches[3], 10),
-      };
+      }
     } catch {
       return {
         type: link.rel,
         url: link.href,
-      };
+      }
     }
-  });
-};
+  })
+}
 
 const transformCarrier = (carrier: ApiCarrier): Initiative => {
   return {
@@ -81,10 +81,10 @@ const transformCarrier = (carrier: ApiCarrier): Initiative => {
     name: carrier.name,
     city: carrier.city,
     country: carrier.country,
-    url: carrier.links.find((l) => l.rel === "self")?.href, // will be replaced by separate resolver resp. used as fallback
+    url: carrier.links.find((l) => l.rel === 'self')?.href, // will be replaced by separate resolver resp. used as fallback
     picture: transformPicture(carrier.picture),
-  };
-};
+  }
+}
 
 const transformProject = (project: ApiProject): Project => {
   return {
@@ -100,30 +100,30 @@ const transformProject = (project: ApiProject): Project => {
     picture: transformPicture(project.profile_picture),
     summary: project.summary,
     description: project.description && cleanUpHtml(project.description),
-    donationUrl: project.links.find((p) => p.rel === "new_donation")!.href,
-    newsUrl: project.links.find((p) => p.rel === "blog_posts")!.href,
+    donationUrl: project.links.find((p) => p.rel === 'new_donation')!.href,
+    newsUrl: project.links.find((p) => p.rel === 'blog_posts')!.href,
     news: [], // will be set by separate resolver
     newsCount: project.blog_post_count,
-  };
-};
+  }
+}
 
 const transformProjectsResponse = (
   response: ApiProjectsResponse,
 ): ProjectsResponse => {
   if (!response.data) {
-    throw new Error(`Invalid response: ${JSON.stringify(response)}`);
+    throw new Error(`Invalid response: ${JSON.stringify(response)}`)
   }
   return {
     totalResults: response.total_entries,
     data: response.data.map(transformProject),
-  };
-};
+  }
+}
 
 // TODO consider returning an object consisting of at least id + slug so that original category URL can be reconstructed
 //  which could be needed in later stories in which we fetch projects of a given category
 const transformProjectCategory = (
   apiProjectCategory: ApiProjectCategory,
-): string => apiProjectCategory.slug;
+): string => apiProjectCategory.slug
 
 const transformNews = (blogPost: ApiBlogPost): News => ({
   id: blogPost.id,
@@ -136,178 +136,176 @@ const transformNews = (blogPost: ApiBlogPost): News => ({
     }
     : undefined,
   body: cleanUpHtml(blogPost.body),
-  url: blogPost.links.find((p) => p.rel === "platform")!.href,
-});
+  url: blogPost.links.find((p) => p.rel === 'platform')!.href,
+})
 
 export const fetchCategories = async (projectId: number): Promise<string[]> => {
   // even though the original query might use a different locale, we are using "en" as locale deliberately
   // betterplace translates category slugs but we need stable identifiers, therefore we default to "en"
-  const href =
-    `https://api.betterplace.org/en/api_v4/projects/${projectId}/categories.json`;
-  logger.info(`fetching project categories from ${href}`);
+  const href = `https://api.betterplace.org/en/api_v4/projects/${projectId}/categories.json`
+  logger.info(`fetching project categories from ${href}`)
   try {
-    const response = await fetch(href);
-    const json = await response.json();
-    const categories = json.data as Array<ApiProjectCategory>;
-    return categories.map(transformProjectCategory);
+    const response = await fetch(href)
+    const json = await response.json()
+    const categories = json.data as Array<ApiProjectCategory>
+    return categories.map(transformProjectCategory)
   } catch (e) {
     logger.warn(
       `Error while fetching project categories from '${href}', using empty array to handle this (somewhat) gracefully`,
       e,
-    );
-    return [];
+    )
+    return []
   }
-};
+}
 
 export const fetchNews = async (
   project: Project,
   parameters: NewsParameters,
 ): Promise<News[]> => {
   const href = project.newsUrl +
-    `?per_page=${parameters.limit || 5}&order=published_at:desc`;
-  logger.info(`fetching blog posts from ${href}`);
+    `?per_page=${parameters.limit || 5}&order=published_at:desc`
+  logger.info(`fetching blog posts from ${href}`)
 
   try {
-    const response = await fetch(href);
-    const json = await response.json();
-    const news = json.data as ApiBlogPost[];
-    return news.map(transformNews);
+    const response = await fetch(href)
+    const json = await response.json()
+    const news = json.data as ApiBlogPost[]
+    return news.map(transformNews)
   } catch (e) {
     logger.warn(
       `Error while fetching blog posts from '${href}', using empty array to handle this (somewhat) gracefully`,
       e,
-    );
-    return [];
+    )
+    return []
   }
-};
+}
 
 export const fetchInitiativeUrl = async (
   initiative: Initiative,
 ): Promise<string | undefined> => {
   if (!initiative.url) {
-    return Promise.resolve(initiative.url);
+    return Promise.resolve(initiative.url)
   }
   try {
-    const response = await fetch(initiative.url);
-    const organisation: ApiOrganisation = await response.json();
-    return organisation.links.find((l) => l.rel === "platform")?.href;
+    const response = await fetch(initiative.url)
+    const organisation: ApiOrganisation = await response.json()
+    return organisation.links.find((l) => l.rel === 'platform')?.href
   } catch (e) {
     logger.warn(
       `Error while fetching organisation url from '${initiative.url}', using api url to handle this (somewhat) gracefully`,
       e,
-    );
-    return initiative.url;
+    )
+    return initiative.url
   }
-};
+}
 
 function _debugP<In>(desc: string | undefined = undefined) {
   return async (elemP: In) => {
-    const elem = await elemP;
-    if (desc) console.debug(desc, elem);
-    else console.debug(elem);
-    return elem;
-  };
+    const elem = await elemP
+    if (desc) console.debug(desc, elem)
+    else console.debug(elem)
+    return elem
+  }
 }
 
 const buildProjectsUrl = (
   { limit = DEFAULT_PAGE_SIZE, offset = 0, location }: ProjectsParameters,
   language: string = DEFAULT_LANGUAGE,
 ): URL => {
-  const page = Math.floor(offset / limit) + 1; // page is NOT zero-based (!), i.e. first page = 1
-  const url = new URL(`${BASE_URL}/${language}/api_v4/projects.json`);
+  const page = Math.floor(offset / limit) + 1 // page is NOT zero-based (!), i.e. first page = 1
+  const url = new URL(`${BASE_URL}/${language}/api_v4/projects.json`)
   url.searchParams.append(
-    "facets",
-    "completed:false|closed:false|prohibit_donations:false",
-  );
-  url.searchParams.append("order", "rank:DESC");
-  url.searchParams.append("page", page.toString());
-  url.searchParams.append("per_page", limit.toString());
+    'facets',
+    'completed:false|closed:false|prohibit_donations:false',
+  )
+  url.searchParams.append('order', 'rank:DESC')
+  url.searchParams.append('page', page.toString())
+  url.searchParams.append('per_page', limit.toString())
   if (location) {
-    url.searchParams.append("scope", "location");
-    url.searchParams.append("q", location);
+    url.searchParams.append('scope', 'location')
+    url.searchParams.append('q', location)
   }
-  return url;
-};
+  return url
+}
 
 const fetchPageOfProjects = async (
   params: ProjectsParameters,
   language: BetterPlaceLanguage = DEFAULT_LANGUAGE,
 ): Promise<ProjectsResponse> => {
-  const url = buildProjectsUrl(params, language);
-  const start = Date.now();
-  logger.info(`fetching projects from ${url}`);
+  const url = buildProjectsUrl(params, language)
+  const start = Date.now()
+  logger.info(`fetching projects from ${url}`)
   try {
-    const fetchResponse = await fetch(url);
-    const jsonResponse = await fetchResponse.json();
-    return transformProjectsResponse(jsonResponse);
+    const fetchResponse = await fetch(url)
+    const jsonResponse = await fetchResponse.json()
+    return transformProjectsResponse(jsonResponse)
   } catch (e) {
     logger.error(
       `Error performing request to ${url}: ${e.message}`,
-    );
-    throw e;
+    )
+    throw e
   } finally {
-    const duration = Date.now() - start;
-    logger.debug(`fetching projects took ${duration} ms`);
+    const duration = Date.now() - start
+    logger.debug(`fetching projects took ${duration} ms`)
   }
-};
+}
 
 // Do not select projects from too far back
-const randomPageForToday = () =>
-  (new Date().setUTCHours(0, 0, 0, 0) / 100000) % MAX_PAGE_FOR_RANDOMIZATION;
+const randomPageForToday = () => (new Date().setUTCHours(0, 0, 0, 0) / 100000) % MAX_PAGE_FOR_RANDOMIZATION
 
 export const fetchProjects = async (
   { offset = 0, limit = DEFAULT_PAGE_SIZE, location }: ProjectsParameters,
   language: BetterPlaceLanguage = DEFAULT_LANGUAGE,
 ): Promise<ProjectsResponse> => {
   // When not filtering: Each day a randomly selected page is sorted to the front
-  const randomPage = randomPageForToday();
-  const isFiltering = !!location;
-  const isFirstPageOfUnfilteredList = offset < limit && !isFiltering;
+  const randomPage = randomPageForToday()
+  const isFiltering = !!location
+  const isFirstPageOfUnfilteredList = offset < limit && !isFiltering
   if (isFirstPageOfUnfilteredList) {
-    logger.info(`fetching random projects from page ${randomPage}`);
+    logger.info(`fetching random projects from page ${randomPage}`)
     const projects = await fetchPageOfProjects({
       offset: randomPage * DEFAULT_PAGE_SIZE,
       limit: DEFAULT_PAGE_SIZE,
-    }, language);
+    }, language)
     return ({
       ...projects,
       data: projects.data.slice(0, limit),
-    });
+    })
   }
   // After one randomly selected page, "normal" pagination starts with offset 0 and skips the random page that was already displayed
-  const afterRandomPage = offset > randomPage * DEFAULT_PAGE_SIZE;
+  const afterRandomPage = offset > randomPage * DEFAULT_PAGE_SIZE
   return fetchPageOfProjects({
     offset: (isFiltering || afterRandomPage) ? offset : offset - limit,
     limit,
     location,
-  }, language);
-};
+  }, language)
+}
 
 export const fetchProject = async (
   { id }: ProjectParameters,
   language: BetterPlaceLanguage = DEFAULT_LANGUAGE,
 ): Promise<Project> => {
-  const url = `${BASE_URL}/${language}/api_v4/projects/${id}.json`;
-  logger.info(`fetching project from ${url}`);
-  const start = Date.now();
+  const url = `${BASE_URL}/${language}/api_v4/projects/${id}.json`
+  logger.info(`fetching project from ${url}`)
+  const start = Date.now()
   try {
-    const response = await fetch(url);
+    const response = await fetch(url)
     if (response.status === 404) {
-      throw new GraphQLError("Not found", {
-        extensions: { "code": ERROR_CODE_NOT_FOUND },
-      });
+      throw new GraphQLError('Not found', {
+        extensions: { 'code': ERROR_CODE_NOT_FOUND },
+      })
     }
-    const json = await response.json();
-    return transformProject(json);
+    const json = await response.json()
+    return transformProject(json)
   } catch (e) {
     if (e.extensions?.code !== ERROR_CODE_NOT_FOUND) {
       logger.error(
         `Error performing request to ${url}: ${e.message}`,
-      );
+      )
     }
-    throw e;
+    throw e
   } finally {
-    const duration = Date.now() - start;
-    logger.debug(`fetching project with ID ${id} took ${duration} ms`);
+    const duration = Date.now() - start
+    logger.debug(`fetching project with ID ${id} took ${duration} ms`)
   }
-};
+}
diff --git a/app/betterplace_test.ts b/app/betterplace_test.ts
index 15cc0ffc83b56dc4305d86e9c945c046bfd1f391..7be2afedbb823eca9d796879eaa08166d03342c6 100644
--- a/app/betterplace_test.ts
+++ b/app/betterplace_test.ts
@@ -11,13 +11,9 @@ import {
   returnsNext,
   Stub,
   stub,
-} from "./dev_deps.ts";
-import {
-  processGqlRequest,
-  ResponsePayload,
-  stubFetch,
-} from "./common_test.ts";
-import { fetchProject, fetchProjects } from "./betterplace.ts";
+} from './dev_deps.ts'
+import { processGqlRequest, ResponsePayload, stubFetch } from './common_test.ts'
+import { fetchProject, fetchProjects } from './betterplace.ts'
 import {
   apiBlogPosts1,
   apiBlogPosts2,
@@ -31,71 +27,69 @@ import {
   categoryPopular,
   expectedProjectsResponse,
   expectedResult,
-} from "./betterplace_test_data.ts";
-import { Project, ProjectsResponse } from "./types.ts";
-import { createGraphQLServer, GraphQLServer } from "./server.ts";
-import { GraphQLError } from "./deps.ts";
+} from './betterplace_test_data.ts'
+import { Project, ProjectsResponse } from './types.ts'
+import { createGraphQLServer, GraphQLServer } from './server.ts'
+import { GraphQLError } from './deps.ts'
 
 const emptyResponse = {
   total_entries: 0,
   offset: 0,
   data: [],
-};
+}
 
-type UrlPrefix = string;
+type UrlPrefix = string
 
 const projectsUrlWithDefaultOptions =
-  "https://api.betterplace.org/de/api_v4/projects.json?facets=completed%3Afalse%7Cclosed%3Afalse%7Cprohibit_donations%3Afalse&order=rank%3ADESC";
+  'https://api.betterplace.org/de/api_v4/projects.json?facets=completed%3Afalse%7Cclosed%3Afalse%7Cprohibit_donations%3Afalse&order=rank%3ADESC'
 
 const noCacheServerConfig = {
   cacheEnabled: false,
   port: 0,
   cacheTtlMsBetterplace: 0,
   fake: false,
-};
+}
 
 const stubFetchByUrlPrefix = (
   responses: Record<UrlPrefix, ResponsePayload>,
 ) => {
-  return stub(globalThis, "fetch", (input) => {
-    const url = input.toString();
+  return stub(globalThis, 'fetch', (input) => {
+    const url = input.toString()
     for (const [urlPrefix, response] of Object.entries(responses)) {
       if (url.startsWith(urlPrefix)) {
         if (response instanceof Error) {
-          return Promise.reject(response);
+          return Promise.reject(response)
         } else {
-          return Promise.resolve(new Response(JSON.stringify(response)));
+          return Promise.resolve(new Response(JSON.stringify(response)))
         }
       }
     }
-    throw Promise.reject(new Error(`Unexpected request URL "${url}"`));
-  });
-};
+    throw Promise.reject(new Error(`Unexpected request URL "${url}"`))
+  })
+}
 
 const validApiResponses = {
-  "https://api.betterplace.org/en/api_v4/projects.json": apiProjectsResult,
-  "https://api.betterplace.org/en/api_v4/projects/1.json": apiProject1,
-  "https://api.betterplace.org/de/api_v4/projects/1.json": apiProject1,
-  "https://api.betterplace.org/en/api_v4/projects/1/categories.json":
-    categoriesResult([categoryEducation]),
-  "https://api.betterplace.org/en/api_v4/projects/2/categories.json":
-    categoriesResult([categoryPopular]),
-  "https://api.betterplace.org/en/api_v4/projects/3/categories.json":
-    categoriesResult([categoryEducation, categoryPopular]),
-  "https://api.betterplace.org/en/api_v4/projects/4/categories.json":
-    categoriesResult([categoryEducation, categoryPopular]),
-  "https://api.betterplace.org/de/api_v4/organisations/1.json":
-    apiOrganisation1,
-  "https://api.betterplace.org/de/api_v4/organisations/2.json":
-    apiOrganisation2,
-  "https://api.betterplace.org/de/api_v4/organisations/3.json":
-    apiOrganisation2,
-  "https://api.betterplace.org/de/api_v4/organisations/4.json":
-    apiOrganisation2,
-  "https://api.betterplace.org/de/api_v4/blog_posts/1.json": apiBlogPosts1,
-  "https://api.betterplace.org/de/api_v4/blog_posts/2.json": apiBlogPosts2,
-  "https://api.betterplace.org/de/api_v4/blog_posts/": apiBlogPostsEmpty,
-};
+  'https://api.betterplace.org/en/api_v4/projects.json': apiProjectsResult,
+  'https://api.betterplace.org/en/api_v4/projects/1.json': apiProject1,
+  'https://api.betterplace.org/de/api_v4/projects/1.json': apiProject1,
+  'https://api.betterplace.org/en/api_v4/projects/1/categories.json': categoriesResult([categoryEducation]),
+  'https://api.betterplace.org/en/api_v4/projects/2/categories.json': categoriesResult([categoryPopular]),
+  'https://api.betterplace.org/en/api_v4/projects/3/categories.json': categoriesResult([
+    categoryEducation,
+    categoryPopular,
+  ]),
+  'https://api.betterplace.org/en/api_v4/projects/4/categories.json': categoriesResult([
+    categoryEducation,
+    categoryPopular,
+  ]),
+  'https://api.betterplace.org/de/api_v4/organisations/1.json': apiOrganisation1,
+  'https://api.betterplace.org/de/api_v4/organisations/2.json': apiOrganisation2,
+  'https://api.betterplace.org/de/api_v4/organisations/3.json': apiOrganisation2,
+  'https://api.betterplace.org/de/api_v4/organisations/4.json': apiOrganisation2,
+  'https://api.betterplace.org/de/api_v4/blog_posts/1.json': apiBlogPosts1,
+  'https://api.betterplace.org/de/api_v4/blog_posts/2.json': apiBlogPosts2,
+  'https://api.betterplace.org/de/api_v4/blog_posts/': apiBlogPostsEmpty,
+}
 
 const projectFragment = `
   id
@@ -146,7 +140,7 @@ const projectFragment = `
   }
   newsUrl
   newsCount
-`;
+`
 
 const queryProjects = (
   graphQLServer: GraphQLServer,
@@ -160,11 +154,11 @@ const queryProjects = (
         ${projectFragment}
       }
     }
-  }`;
+  }`
   return processGqlRequest(graphQLServer, query).then(
     (result) => result?.projects as ProjectsResponse,
-  );
-};
+  )
+}
 
 const queryProject = async (
   graphQLServer: GraphQLServer,
@@ -180,336 +174,327 @@ const queryProject = async (
     }`,
     { id: apiProject1.id },
     headers,
-  );
+  )
 
-  return (await promise)?.project as Project;
-};
+  return (await promise)?.project as Project
+}
 
 const urlForPage = (page = 1, pageSize = 10) =>
-  new URL(`${projectsUrlWithDefaultOptions}&page=${page}&per_page=${pageSize}`);
+  new URL(`${projectsUrlWithDefaultOptions}&page=${page}&per_page=${pageSize}`)
 
-describe("betterplace", () => {
-  let fetchStub: Stub;
-  let time: FakeTime;
+describe('betterplace', () => {
+  let fetchStub: Stub
+  let time: FakeTime
 
   beforeEach(() => {
-    time = new FakeTime(new Date(2023, 8, 12, 12));
-  });
+    time = new FakeTime(new Date(2023, 8, 12, 12))
+  })
 
   afterEach(() => {
-    fetchStub?.restore();
-    time?.restore();
-  });
+    fetchStub?.restore()
+    time?.restore()
+  })
 
-  describe("fetching project list", () => {
-    it("calls api with correct parameters", async () => {
-      fetchStub = stubFetch(emptyResponse);
+  describe('fetching project list', () => {
+    it('calls api with correct parameters', async () => {
+      fetchStub = stubFetch(emptyResponse)
 
-      await fetchProjects({ limit: 10, offset: 30 }, "de");
+      await fetchProjects({ limit: 10, offset: 30 }, 'de')
 
-      const expectedUrl = urlForPage(3);
-      assertSpyCall(fetchStub, 0, { args: [expectedUrl] });
-    });
+      const expectedUrl = urlForPage(3)
+      assertSpyCall(fetchStub, 0, { args: [expectedUrl] })
+    })
 
-    it("calls api with correct parameters for location search", async () => {
-      fetchStub = stubFetch(emptyResponse);
+    it('calls api with correct parameters for location search', async () => {
+      fetchStub = stubFetch(emptyResponse)
 
-      await fetchProjects({ limit: 10, offset: 20, location: "Hamburg" }, "de");
+      await fetchProjects({ limit: 10, offset: 20, location: 'Hamburg' }, 'de')
 
       const expectedUrl = new URL(
         projectsUrlWithDefaultOptions +
-          "&page=3&per_page=10&scope=location&q=Hamburg",
-      );
-      assertSpyCall(fetchStub, 0, { args: [expectedUrl] });
-    });
+          '&page=3&per_page=10&scope=location&q=Hamburg',
+      )
+      assertSpyCall(fetchStub, 0, { args: [expectedUrl] })
+    })
 
-    it("properly encodes query for location search", async () => {
-      fetchStub = stubFetch(emptyResponse);
+    it('properly encodes query for location search', async () => {
+      fetchStub = stubFetch(emptyResponse)
 
       await fetchProjects(
         {
           limit: 10,
           offset: 20,
-          location: "Straße 123, 20535 Hamburg",
+          location: 'Straße 123, 20535 Hamburg',
         },
-        "de",
-      );
+        'de',
+      )
 
       const expectedUrl = new URL(
         projectsUrlWithDefaultOptions +
-          "&page=3&per_page=10&scope=location&q=Stra%C3%9Fe+123%2C+20535+Hamburg",
-      );
-      assertSpyCall(fetchStub, 0, { args: [expectedUrl] });
-    });
+          '&page=3&per_page=10&scope=location&q=Stra%C3%9Fe+123%2C+20535+Hamburg',
+      )
+      assertSpyCall(fetchStub, 0, { args: [expectedUrl] })
+    })
 
-    it("calls api with correct parameters for empty location search", async () => {
-      fetchStub = stubFetch(emptyResponse);
+    it('calls api with correct parameters for empty location search', async () => {
+      fetchStub = stubFetch(emptyResponse)
 
-      await fetchProjects({ limit: 10, offset: 30, location: "" }, "de");
+      await fetchProjects({ limit: 10, offset: 30, location: '' }, 'de')
 
-      const expectedUrl = urlForPage(3);
-      assertSpyCall(fetchStub, 0, { args: [expectedUrl] });
-    });
+      const expectedUrl = urlForPage(3)
+      assertSpyCall(fetchStub, 0, { args: [expectedUrl] })
+    })
 
-    it("queries a random page for the first unfiltered page", async () => {
-      fetchStub = stubFetch(emptyResponse);
+    it('queries a random page for the first unfiltered page', async () => {
+      fetchStub = stubFetch(emptyResponse)
 
-      await fetchProjects({}, "de");
+      await fetchProjects({}, 'de')
 
-      assertSpyCall(fetchStub, 0, { args: [urlForPage(9)] });
-    });
+      assertSpyCall(fetchStub, 0, { args: [urlForPage(9)] })
+    })
 
-    it("queries a different random page the next day", async () => {
-      time.tick(24 * 60 * 60 * 1000);
-      fetchStub = stubFetch(emptyResponse);
+    it('queries a different random page the next day', async () => {
+      time.tick(24 * 60 * 60 * 1000)
+      fetchStub = stubFetch(emptyResponse)
 
-      await fetchProjects({}, "de");
+      await fetchProjects({}, 'de')
 
-      assertSpyCall(fetchStub, 0, { args: [urlForPage(3)] });
-    });
+      assertSpyCall(fetchStub, 0, { args: [urlForPage(3)] })
+    })
 
-    it("resumes normal pagination after the first page", async () => {
+    it('resumes normal pagination after the first page', async () => {
       fetchStub = stub(
         globalThis,
-        "fetch",
+        'fetch',
         returnsNext(
-          Array(3).fill(emptyResponse).map((response) =>
-            Promise.resolve(new Response(JSON.stringify(response)))
-          ),
+          Array(3).fill(emptyResponse).map((response) => Promise.resolve(new Response(JSON.stringify(response)))),
         ),
-      );
+      )
 
-      await fetchProjects({}, "de");
-      await fetchProjects({ offset: 10 }, "de");
-      await fetchProjects({ offset: 20 }, "de");
+      await fetchProjects({}, 'de')
+      await fetchProjects({ offset: 10 }, 'de')
+      await fetchProjects({ offset: 20 }, 'de')
 
-      assertSpyCall(fetchStub, 0, { args: [urlForPage(9)] });
-      assertSpyCall(fetchStub, 1, { args: [urlForPage(1)] });
-      assertSpyCall(fetchStub, 2, { args: [urlForPage(2)] });
-    });
+      assertSpyCall(fetchStub, 0, { args: [urlForPage(9)] })
+      assertSpyCall(fetchStub, 1, { args: [urlForPage(1)] })
+      assertSpyCall(fetchStub, 2, { args: [urlForPage(2)] })
+    })
 
-    it("skips the randomly selected page in normal pagination", async () => {
+    it('skips the randomly selected page in normal pagination', async () => {
       fetchStub = stub(
         globalThis,
-        "fetch",
+        'fetch',
         returnsNext(
-          Array(3).fill(emptyResponse).map((response) =>
-            Promise.resolve(new Response(JSON.stringify(response)))
-          ),
+          Array(3).fill(emptyResponse).map((response) => Promise.resolve(new Response(JSON.stringify(response)))),
         ),
-      );
+      )
 
-      await fetchProjects({}, "de");
-      await fetchProjects({ offset: 80 }, "de");
-      await fetchProjects({ offset: 90 }, "de");
+      await fetchProjects({}, 'de')
+      await fetchProjects({ offset: 80 }, 'de')
+      await fetchProjects({ offset: 90 }, 'de')
 
-      assertSpyCall(fetchStub, 0, { args: [urlForPage(9)] });
-      assertSpyCall(fetchStub, 1, { args: [urlForPage(8)] });
-      assertSpyCall(fetchStub, 2, { args: [urlForPage(10)] });
-    });
+      assertSpyCall(fetchStub, 0, { args: [urlForPage(9)] })
+      assertSpyCall(fetchStub, 1, { args: [urlForPage(8)] })
+      assertSpyCall(fetchStub, 2, { args: [urlForPage(10)] })
+    })
 
-    it("does not query random projects for the first page when filtering for location", async () => {
-      fetchStub = stubFetch(emptyResponse);
+    it('does not query random projects for the first page when filtering for location', async () => {
+      fetchStub = stubFetch(emptyResponse)
 
-      await fetchProjects({ limit: 10, offset: 0, location: "Hamburg" }, "de");
+      await fetchProjects({ limit: 10, offset: 0, location: 'Hamburg' }, 'de')
 
       const expectedUrl = new URL(
         projectsUrlWithDefaultOptions +
-          "&page=1&per_page=10&scope=location&q=Hamburg",
-      );
-      assertSpyCall(fetchStub, 0, { args: [expectedUrl] });
-    });
+          '&page=1&per_page=10&scope=location&q=Hamburg',
+      )
+      assertSpyCall(fetchStub, 0, { args: [expectedUrl] })
+    })
 
-    it("correctly parses empty response", async () => {
-      fetchStub = stubFetch(emptyResponse);
+    it('correctly parses empty response', async () => {
+      fetchStub = stubFetch(emptyResponse)
 
-      const result = await fetchProjects({ offset: 10 });
+      const result = await fetchProjects({ offset: 10 })
 
-      assertEquals(result, { totalResults: 0, data: [] });
-    });
+      assertEquals(result, { totalResults: 0, data: [] })
+    })
 
-    it("correctly parses project list", async () => {
-      fetchStub = stubFetchByUrlPrefix(validApiResponses);
+    it('correctly parses project list', async () => {
+      fetchStub = stubFetchByUrlPrefix(validApiResponses)
 
-      const graphQLServer = createGraphQLServer(noCacheServerConfig);
-      const result = await queryProjects(graphQLServer);
+      const graphQLServer = createGraphQLServer(noCacheServerConfig)
+      const result = await queryProjects(graphQLServer)
 
-      assertEquals(result, expectedProjectsResponse);
-    });
+      assertEquals(result, expectedProjectsResponse)
+    })
 
-    it("throws error for invalid projects response", async () => {
+    it('throws error for invalid projects response', async () => {
       fetchStub = stub(
         globalThis,
-        "fetch",
-        returnsNext([Promise.resolve(new Response("foobar"))]),
-      );
+        'fetch',
+        returnsNext([Promise.resolve(new Response('foobar'))]),
+      )
 
-      await assertRejects(() => fetchProjects({ offset: 10 }));
-    });
+      await assertRejects(() => fetchProjects({ offset: 10 }))
+    })
 
-    it("throws error for API error response", async () => {
+    it('throws error for API error response', async () => {
       fetchStub = stubFetch({
-        status: "internal_server_error",
-        "status_code": 500,
-      });
+        status: 'internal_server_error',
+        'status_code': 500,
+      })
 
-      await assertRejects(() => fetchProjects({ offset: 10 }));
-    });
+      await assertRejects(() => fetchProjects({ offset: 10 }))
+    })
 
-    it("returns empty categories for invalid category responses", async () => {
+    it('returns empty categories for invalid category responses', async () => {
       fetchStub = stubFetchByUrlPrefix({
         ...validApiResponses,
-        "https://api.betterplace.org/en/api_v4/projects/1/categories.json":
-          new Error("Expected error"),
-      });
+        'https://api.betterplace.org/en/api_v4/projects/1/categories.json': new Error('Expected error'),
+      })
 
-      const graphQLServer = createGraphQLServer(noCacheServerConfig);
-      const result = await queryProjects(graphQLServer);
+      const graphQLServer = createGraphQLServer(noCacheServerConfig)
+      const result = await queryProjects(graphQLServer)
 
-      const project1 = result.data.find((p) => p.id === 1);
-      assertExists(project1);
-      assertEquals(project1?.categories, []);
-    });
+      const project1 = result.data.find((p) => p.id === 1)
+      assertExists(project1)
+      assertEquals(project1?.categories, [])
+    })
 
-    it("returns api url for invalid organisation responses", async () => {
+    it('returns api url for invalid organisation responses', async () => {
       fetchStub = stubFetchByUrlPrefix({
         ...validApiResponses,
-        "https://api.betterplace.org/de/api_v4/organisations/1.json": new Error(
-          "Expected error",
+        'https://api.betterplace.org/de/api_v4/organisations/1.json': new Error(
+          'Expected error',
         ),
-      });
+      })
 
-      const graphQLServer = createGraphQLServer(noCacheServerConfig);
-      const result = await queryProjects(graphQLServer);
+      const graphQLServer = createGraphQLServer(noCacheServerConfig)
+      const result = await queryProjects(graphQLServer)
 
-      const project1 = result.data.find((p) => p.id === 1);
-      assertExists(project1?.initiative);
+      const project1 = result.data.find((p) => p.id === 1)
+      assertExists(project1?.initiative)
       assertEquals(
         project1?.initiative.url,
-        "https://api.betterplace.org/de/api_v4/organisations/1.json",
-      );
-    });
+        'https://api.betterplace.org/de/api_v4/organisations/1.json',
+      )
+    })
 
-    it("returns empty news for invalid blog post responses", async () => {
+    it('returns empty news for invalid blog post responses', async () => {
       fetchStub = stubFetchByUrlPrefix({
         ...validApiResponses,
-        "https://api.betterplace.org/de/api_v4/blog_posts/1.json": new Error(
-          "Expected error",
+        'https://api.betterplace.org/de/api_v4/blog_posts/1.json': new Error(
+          'Expected error',
         ),
-      });
+      })
 
-      const graphQLServer = createGraphQLServer(noCacheServerConfig);
-      const result = await queryProjects(graphQLServer);
-      const project1 = result.data.find((p) => p.id === 1);
-      assertExists(project1);
-      assertEquals(project1?.news, []);
-    });
+      const graphQLServer = createGraphQLServer(noCacheServerConfig)
+      const result = await queryProjects(graphQLServer)
+      const project1 = result.data.find((p) => p.id === 1)
+      assertExists(project1)
+      assertEquals(project1?.news, [])
+    })
 
-    it("returns cached results on recurring requests", async () => {
-      fetchStub = stubFetchByUrlPrefix(validApiResponses);
+    it('returns cached results on recurring requests', async () => {
+      fetchStub = stubFetchByUrlPrefix(validApiResponses)
       const graphQLServer = createGraphQLServer({
         cacheEnabled: true,
         port: 0,
         cacheTtlMsBetterplace: 1000,
         fake: false,
-      });
-      const result = await queryProjects(graphQLServer);
-      assertEquals(result, expectedProjectsResponse);
+      })
+      const result = await queryProjects(graphQLServer)
+      assertEquals(result, expectedProjectsResponse)
 
-      fetchStub?.restore();
+      fetchStub?.restore()
       fetchStub = stubFetchByUrlPrefix({
-        "https://api.betterplace.org/en/api_v4/projects.json": new Error(
-          "Expected error",
+        'https://api.betterplace.org/en/api_v4/projects.json': new Error(
+          'Expected error',
         ),
-      });
-      const result2 = await queryProjects(graphQLServer);
-      assertEquals(result2, expectedProjectsResponse);
+      })
+      const result2 = await queryProjects(graphQLServer)
+      assertEquals(result2, expectedProjectsResponse)
 
       // clean up cache timeout
-      await time.delay(1000);
-    });
-  });
+      await time.delay(1000)
+    })
+  })
 
-  describe("fetching single project", () => {
-    it("correctly retrieves a project by ID", async () => {
-      fetchStub = stubFetchByUrlPrefix(validApiResponses);
+  describe('fetching single project', () => {
+    it('correctly retrieves a project by ID', async () => {
+      fetchStub = stubFetchByUrlPrefix(validApiResponses)
 
-      const graphQLServer = createGraphQLServer(noCacheServerConfig);
-      const result = await queryProject(graphQLServer);
+      const graphQLServer = createGraphQLServer(noCacheServerConfig)
+      const result = await queryProject(graphQLServer)
 
-      assertEquals(result, expectedResult);
-    });
+      assertEquals(result, expectedResult)
+    })
 
-    it("correctly extracts language from locale", async () => {
-      fetchStub = stubFetchByUrlPrefix(validApiResponses);
+    it('correctly extracts language from locale', async () => {
+      fetchStub = stubFetchByUrlPrefix(validApiResponses)
 
-      const graphQLServer = createGraphQLServer(noCacheServerConfig);
+      const graphQLServer = createGraphQLServer(noCacheServerConfig)
       const result = await queryProject(graphQLServer, {
-        "accept-language": "de-DE",
-      });
+        'accept-language': 'de-DE',
+      })
 
-      assertEquals(result, expectedResult);
-      const expectedUrl =
-        "https://api.betterplace.org/de/api_v4/projects/1.json";
-      assertSpyCall(fetchStub, 0, { args: [expectedUrl] });
-    });
+      assertEquals(result, expectedResult)
+      const expectedUrl = 'https://api.betterplace.org/de/api_v4/projects/1.json'
+      assertSpyCall(fetchStub, 0, { args: [expectedUrl] })
+    })
 
-    it("uses correct language as default if requested language is not supported", async () => {
-      fetchStub = stubFetchByUrlPrefix(validApiResponses);
+    it('uses correct language as default if requested language is not supported', async () => {
+      fetchStub = stubFetchByUrlPrefix(validApiResponses)
 
-      const graphQLServer = createGraphQLServer(noCacheServerConfig);
+      const graphQLServer = createGraphQLServer(noCacheServerConfig)
       const result = await queryProject(graphQLServer, {
-        "accept-language": "es",
-      });
+        'accept-language': 'es',
+      })
 
-      assertEquals(result, expectedResult);
-      const expectedUrl =
-        "https://api.betterplace.org/en/api_v4/projects/1.json";
-      assertSpyCall(fetchStub, 0, { args: [expectedUrl] });
-    });
+      assertEquals(result, expectedResult)
+      const expectedUrl = 'https://api.betterplace.org/en/api_v4/projects/1.json'
+      assertSpyCall(fetchStub, 0, { args: [expectedUrl] })
+    })
 
-    it("calls api with correct parameters for fetching a project by ID", async () => {
-      fetchStub = stubFetch(apiProject1);
+    it('calls api with correct parameters for fetching a project by ID', async () => {
+      fetchStub = stubFetch(apiProject1)
 
-      await fetchProject({ id: 1 }, "de");
+      await fetchProject({ id: 1 }, 'de')
 
-      const expectedUrl =
-        "https://api.betterplace.org/de/api_v4/projects/1.json";
-      assertSpyCall(fetchStub, 0, { args: [expectedUrl] });
-    });
+      const expectedUrl = 'https://api.betterplace.org/de/api_v4/projects/1.json'
+      assertSpyCall(fetchStub, 0, { args: [expectedUrl] })
+    })
 
-    it("uses default locale if missing for fetching a project by ID", async () => {
-      fetchStub = stubFetch(apiProject1);
+    it('uses default locale if missing for fetching a project by ID', async () => {
+      fetchStub = stubFetch(apiProject1)
 
-      await fetchProject({ id: 1 });
+      await fetchProject({ id: 1 })
 
-      const expectedUrl =
-        "https://api.betterplace.org/en/api_v4/projects/1.json";
-      assertSpyCall(fetchStub, 0, { args: [expectedUrl] });
-    });
+      const expectedUrl = 'https://api.betterplace.org/en/api_v4/projects/1.json'
+      assertSpyCall(fetchStub, 0, { args: [expectedUrl] })
+    })
 
-    it("throws error for invalid project response", async () => {
+    it('throws error for invalid project response', async () => {
       fetchStub = stub(
         globalThis,
-        "fetch",
-        returnsNext([Promise.resolve(new Response("foobar"))]),
-      );
+        'fetch',
+        returnsNext([Promise.resolve(new Response('foobar'))]),
+      )
 
-      await assertRejects(() => fetchProject({ id: 123 }));
-    });
+      await assertRejects(() => fetchProject({ id: 123 }))
+    })
 
-    it("throws NOT_FOUND error for 404 response", async () => {
+    it('throws NOT_FOUND error for 404 response', async () => {
       fetchStub = stub(
         globalThis,
-        "fetch",
+        'fetch',
         returnsNext([Promise.resolve({ status: 404 } as Response)]),
-      );
+      )
 
       await assertRejects(
         () => fetchProject({ id: 123 }),
         GraphQLError,
-        "Not found",
-      );
-    });
-  });
-});
+        'Not found',
+      )
+    })
+  })
+})
diff --git a/app/betterplace_test_data.ts b/app/betterplace_test_data.ts
index ece93d9eb566f2d3b8f384322a86f441ecd7c0cc..3c3f38d0260eec542c0dfbf74b6b1af0e920b8e9 100644
--- a/app/betterplace_test_data.ts
+++ b/app/betterplace_test_data.ts
@@ -6,89 +6,88 @@ import {
   ApiProject,
   ApiProjectCategory,
   ApiProjectsResponse,
-} from "./api_types.ts";
-import { Initiative, News, Project, ProjectsResponse } from "./types.ts";
+} from './api_types.ts'
+import { Initiative, News, Project, ProjectsResponse } from './types.ts'
 
 const apiProjectCarrier1: ApiCarrier = {
   id: 1,
-  name: "Carrier 1",
-  city: "Berlin",
-  country: "Deutschland",
+  name: 'Carrier 1',
+  city: 'Berlin',
+  country: 'Deutschland',
   picture: {
     links: [
       {
-        "rel": "fill_100x100",
-        "href":
-          "https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/000/045/fill_100x100_original_ARCHE_Logo_rgb_pos.jpg",
+        'rel': 'fill_100x100',
+        'href':
+          'https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/000/045/fill_100x100_original_ARCHE_Logo_rgb_pos.jpg',
       },
       {
-        "rel": "original",
-        "href":
-          "https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/000/045/crop_original_original_ARCHE_Logo_rgb_pos.jpg",
+        'rel': 'original',
+        'href':
+          'https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/000/045/crop_original_original_ARCHE_Logo_rgb_pos.jpg',
       },
     ],
   },
   links: [
     {
-      "rel": "self",
-      "href": "https://api.betterplace.org/de/api_v4/organisations/1.json",
+      'rel': 'self',
+      'href': 'https://api.betterplace.org/de/api_v4/organisations/1.json',
     },
   ],
-};
+}
 
 const apiProjectCarrier2: ApiCarrier = {
   id: 2,
-  name: "Carrier 2",
-  city: "Berlin",
-  country: "Deutschland",
+  name: 'Carrier 2',
+  city: 'Berlin',
+  country: 'Deutschland',
   picture: {
     links: [
       {
-        "rel": "fill_100x100",
-        "href":
-          "https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/025/417/fill_100x100_sea_watch_logo.png",
+        'rel': 'fill_100x100',
+        'href':
+          'https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/025/417/fill_100x100_sea_watch_logo.png',
       },
       {
-        "rel": "original",
-        "href":
-          "https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/025/417/crop_original_sea_watch_logo.png",
+        'rel': 'original',
+        'href':
+          'https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/025/417/crop_original_sea_watch_logo.png',
       },
     ],
   },
   links: [
     {
-      "rel": "self",
-      "href": "https://api.betterplace.org/de/api_v4/organisations/2.json",
+      'rel': 'self',
+      'href': 'https://api.betterplace.org/de/api_v4/organisations/2.json',
     },
   ],
-};
+}
 
 export const apiOrganisation1: ApiOrganisation = {
   links: [
     {
-      "rel": "platform",
-      "href":
-        "https://www.betterplace.org/de/organisations/5147-berliner-obdachlosenhilfe-e-v",
+      'rel': 'platform',
+      'href': 'https://www.betterplace.org/de/organisations/5147-berliner-obdachlosenhilfe-e-v',
     },
   ],
-};
+}
 
 export const apiOrganisation2: ApiOrganisation = {
   links: [
     {
-      "rel": "platform",
-      "href": "https://www.betterplace.org/de/organisations/25435-sea-eye-e-v",
+      'rel': 'platform',
+      'href': 'https://www.betterplace.org/de/organisations/25435-sea-eye-e-v',
     },
   ],
-};
+}
 
 export const apiProject1: ApiProject = {
   id: 1,
-  title: "Project 1",
-  summary: "Summary Project 1",
-  description: "<div>Description Project 1</div>",
-  city: "Kiew",
-  country: "Ukraine",
+  title: 'Project 1',
+  summary: 'Summary Project 1',
+  description: '<div>Description Project 1</div>',
+  city: 'Kiew',
+  country: 'Ukraine',
   donations_count: 42,
   progress_percentage: 33,
   open_amount_in_cents: 421234,
@@ -96,44 +95,43 @@ export const apiProject1: ApiProject = {
   profile_picture: {
     links: [
       {
-        "rel": "fill_100x100",
-        "href": "https://www.example.com/image1_resized2.jpg",
+        'rel': 'fill_100x100',
+        'href': 'https://www.example.com/image1_resized2.jpg',
       },
       {
-        "rel": "fill_410x214",
-        "href": "https://www.example.com/image1_resized1.jpg",
+        'rel': 'fill_410x214',
+        'href': 'https://www.example.com/image1_resized1.jpg',
       },
       {
-        "rel": "original",
-        "href": "https://www.example.com/image1.jpg",
+        'rel': 'original',
+        'href': 'https://www.example.com/image1.jpg',
       },
     ],
   },
   links: [
     {
-      "rel": "categories",
-      "href":
-        "https://api.betterplace.org/en/api_v4/projects/1/categories.json",
+      'rel': 'categories',
+      'href': 'https://api.betterplace.org/en/api_v4/projects/1/categories.json',
     },
     {
-      "rel": "new_donation",
-      "href": "https://www.betterplace.org/de/donate/platform/projects/1",
+      'rel': 'new_donation',
+      'href': 'https://www.betterplace.org/de/donate/platform/projects/1',
     },
     {
-      "rel": "blog_posts",
-      "href": "https://api.betterplace.org/de/api_v4/blog_posts/1.json",
+      'rel': 'blog_posts',
+      'href': 'https://api.betterplace.org/de/api_v4/blog_posts/1.json',
     },
   ],
   carrier: apiProjectCarrier1,
-};
+}
 
 const apiProject2: ApiProject = {
   id: 2,
-  title: "Project 2",
-  summary: "Summary Project 2",
-  description: "Description <b>Project 2</b>",
-  city: "Kiew",
-  country: "Ukraine",
+  title: 'Project 2',
+  summary: 'Summary Project 2',
+  description: 'Description <b>Project 2</b>',
+  city: 'Kiew',
+  country: 'Ukraine',
   donations_count: 13,
   progress_percentage: 10,
   open_amount_in_cents: 1234567,
@@ -142,25 +140,24 @@ const apiProject2: ApiProject = {
     links: [],
   },
   links: [{
-    "rel": "categories",
-    "href": "https://api.betterplace.org/en/api_v4/projects/2/categories.json",
+    'rel': 'categories',
+    'href': 'https://api.betterplace.org/en/api_v4/projects/2/categories.json',
   }, {
-    "rel": "new_donation",
-    "href": "https://www.betterplace.org/de/donate/platform/projects/2",
+    'rel': 'new_donation',
+    'href': 'https://www.betterplace.org/de/donate/platform/projects/2',
   }, {
-    "rel": "blog_posts",
-    "href": "https://api.betterplace.org/de/api_v4/blog_posts/2.json",
+    'rel': 'blog_posts',
+    'href': 'https://api.betterplace.org/de/api_v4/blog_posts/2.json',
   }],
   carrier: apiProjectCarrier1,
-};
+}
 
 const apiProject3: ApiProject = {
   id: 3,
-  title: "Project 3",
-  summary: "Summary Project 3",
-  description:
-    '<p>Description <a href="#">Project 3</a><br><img src="#" /></p>',
-  city: "Kiew",
+  title: 'Project 3',
+  summary: 'Summary Project 3',
+  description: '<p>Description <a href="#">Project 3</a><br><img src="#" /></p>',
+  city: 'Kiew',
   country: null,
   donations_count: 0,
   progress_percentage: 0,
@@ -170,25 +167,25 @@ const apiProject3: ApiProject = {
     links: [],
   },
   links: [{
-    "rel": "categories",
-    "href": "https://api.betterplace.org/en/api_v4/projects/3/categories.json",
+    'rel': 'categories',
+    'href': 'https://api.betterplace.org/en/api_v4/projects/3/categories.json',
   }, {
-    "rel": "new_donation",
-    "href": "https://www.betterplace.org/de/donate/platform/projects/3",
+    'rel': 'new_donation',
+    'href': 'https://www.betterplace.org/de/donate/platform/projects/3',
   }, {
-    "rel": "blog_posts",
-    "href": "https://api.betterplace.org/de/api_v4/blog_posts/3.json",
+    'rel': 'blog_posts',
+    'href': 'https://api.betterplace.org/de/api_v4/blog_posts/3.json',
   }],
   carrier: apiProjectCarrier2,
-};
+}
 
 const apiProject4: ApiProject = {
   id: 4,
-  title: "Project 4",
+  title: 'Project 4',
   summary: null,
   description: null,
   city: null,
-  country: "Ukraine",
+  country: 'Ukraine',
   donations_count: 0,
   progress_percentage: 0,
   open_amount_in_cents: 1200000,
@@ -197,17 +194,17 @@ const apiProject4: ApiProject = {
     links: [],
   },
   links: [{
-    "rel": "categories",
-    "href": "https://api.betterplace.org/en/api_v4/projects/4/categories.json",
+    'rel': 'categories',
+    'href': 'https://api.betterplace.org/en/api_v4/projects/4/categories.json',
   }, {
-    "rel": "new_donation",
-    "href": "https://www.betterplace.org/de/donate/platform/projects/4",
+    'rel': 'new_donation',
+    'href': 'https://www.betterplace.org/de/donate/platform/projects/4',
   }, {
-    "rel": "blog_posts",
-    "href": "https://api.betterplace.org/de/api_v4/blog_posts/4.json",
+    'rel': 'blog_posts',
+    'href': 'https://api.betterplace.org/de/api_v4/blog_posts/4.json',
   }],
   carrier: apiProjectCarrier2,
-};
+}
 
 export const apiProjectsResult: ApiProjectsResponse = {
   total_entries: 123,
@@ -218,25 +215,25 @@ export const apiProjectsResult: ApiProjectsResponse = {
     apiProject3,
     apiProject4,
   ],
-};
+}
 
 export const categoryEducation: ApiProjectCategory = {
   id: 3,
-  created_at: "2016-12-13T16:18:14+01:00",
-  updated_at: "2018-12-03T17:26:13+01:00",
-  name: "Education",
-  slug: "education",
+  created_at: '2016-12-13T16:18:14+01:00',
+  updated_at: '2018-12-03T17:26:13+01:00',
+  name: 'Education',
+  slug: 'education',
   links: [],
-};
+}
 
 export const categoryPopular: ApiProjectCategory = {
   id: 44,
-  created_at: "2018-08-13T17:01:27+02:00",
-  updated_at: "2021-07-19T11:40:13+02:00",
-  name: "Popular",
-  slug: "popular",
+  created_at: '2018-08-13T17:01:27+02:00',
+  updated_at: '2021-07-19T11:40:13+02:00',
+  name: 'Popular',
+  slug: 'popular',
   links: [],
-};
+}
 
 export const categoriesResult = (
   categories: Array<ApiProjectCategory>,
@@ -248,289 +245,288 @@ export const categoriesResult = (
     current_page: 1,
     per_page: 20,
     data: categories,
-  };
-};
+  }
+}
 
 const blogPost1: ApiBlogPost = {
   id: 1,
-  "title": "Mirwais",
-  "published_at": "2009-03-11T20:46:27+01:00",
-  "body": "<p>Lorem ipsum</p>",
-  "author": {
-    "name": "Miray Heinrich",
-    "picture": {
-      "links": [
+  'title': 'Mirwais',
+  'published_at': '2009-03-11T20:46:27+01:00',
+  'body': '<p>Lorem ipsum</p>',
+  'author': {
+    'name': 'Miray Heinrich',
+    'picture': {
+      'links': [
         {
-          "rel": "fill_100x100",
-          "href":
-            "https://betterplace-assets.betterplace.org/uploads/user/profile_picture/000/009/238/fill_100x100_bp1584570257_original_maxn_skate.jpg",
+          'rel': 'fill_100x100',
+          'href':
+            'https://betterplace-assets.betterplace.org/uploads/user/profile_picture/000/009/238/fill_100x100_bp1584570257_original_maxn_skate.jpg',
         },
         {
-          "rel": "original",
-          "href":
-            "https://betterplace-assets.betterplace.org/uploads/user/profile_picture/000/009/238/crop_original_bp1584570257_original_maxn_skate.jpg",
+          'rel': 'original',
+          'href':
+            'https://betterplace-assets.betterplace.org/uploads/user/profile_picture/000/009/238/crop_original_bp1584570257_original_maxn_skate.jpg',
         },
       ],
     },
   },
-  "links": [
+  'links': [
     {
-      "rel": "platform",
-      "href":
-        "https://www.betterplace.org/de/projects/1114-unterstuetze-skateistan-sport-bildung-fuer-kinder/news/3917#ppp-sticky-anchor",
+      'rel': 'platform',
+      'href':
+        'https://www.betterplace.org/de/projects/1114-unterstuetze-skateistan-sport-bildung-fuer-kinder/news/3917#ppp-sticky-anchor',
     },
   ],
-};
+}
 
 const blogPost2: ApiBlogPost = {
   id: 1,
-  "title": "Blog post 2",
-  "published_at": "2009-03-11T20:46:27+01:00",
-  "body": '<p>Lorem ipsum</p><img src="www.example.com/test.jpg"',
-  "links": [
+  'title': 'Blog post 2',
+  'published_at': '2009-03-11T20:46:27+01:00',
+  'body': '<p>Lorem ipsum</p><img src="www.example.com/test.jpg"',
+  'links': [
     {
-      "rel": "platform",
-      "href":
-        "https://www.betterplace.org/de/projects/1114-unterstuetze-skateistan-sport-bildung-fuer-kinder/news/3917#ppp-sticky-anchor",
+      'rel': 'platform',
+      'href':
+        'https://www.betterplace.org/de/projects/1114-unterstuetze-skateistan-sport-bildung-fuer-kinder/news/3917#ppp-sticky-anchor',
     },
   ],
-};
+}
 
 export const apiBlogPosts1: ApiBlogPostResponse = {
   total_entries: 2,
   data: [blogPost1, blogPost2],
-};
+}
 
 export const apiBlogPosts2: ApiBlogPostResponse = {
   total_entries: 1,
   data: [blogPost1],
-};
+}
 
 export const apiBlogPostsEmpty: ApiBlogPostResponse = {
   total_entries: 0,
   data: [],
-};
+}
 
 const expectedNews1: News = {
   author: {
-    name: "Miray Heinrich",
+    name: 'Miray Heinrich',
     picture: [
       {
         height: 100,
-        type: "fill",
+        type: 'fill',
         url:
-          "https://betterplace-assets.betterplace.org/uploads/user/profile_picture/000/009/238/fill_100x100_bp1584570257_original_maxn_skate.jpg",
+          'https://betterplace-assets.betterplace.org/uploads/user/profile_picture/000/009/238/fill_100x100_bp1584570257_original_maxn_skate.jpg',
         width: 100,
       },
       {
         height: null,
-        type: "original",
+        type: 'original',
         url:
-          "https://betterplace-assets.betterplace.org/uploads/user/profile_picture/000/009/238/crop_original_bp1584570257_original_maxn_skate.jpg",
+          'https://betterplace-assets.betterplace.org/uploads/user/profile_picture/000/009/238/crop_original_bp1584570257_original_maxn_skate.jpg',
         width: null,
       },
     ],
   },
-  body: "Lorem ipsum",
+  body: 'Lorem ipsum',
   id: 1,
-  publishDate: "2009-03-11T20:46:27+01:00",
-  title: "Mirwais",
+  publishDate: '2009-03-11T20:46:27+01:00',
+  title: 'Mirwais',
   url:
-    "https://www.betterplace.org/de/projects/1114-unterstuetze-skateistan-sport-bildung-fuer-kinder/news/3917#ppp-sticky-anchor",
-};
+    'https://www.betterplace.org/de/projects/1114-unterstuetze-skateistan-sport-bildung-fuer-kinder/news/3917#ppp-sticky-anchor',
+}
 
 const expectedNews2: News = {
   author: null,
-  body: "Lorem ipsum",
+  body: 'Lorem ipsum',
   id: 1,
-  publishDate: "2009-03-11T20:46:27+01:00",
-  title: "Blog post 2",
+  publishDate: '2009-03-11T20:46:27+01:00',
+  title: 'Blog post 2',
   url:
-    "https://www.betterplace.org/de/projects/1114-unterstuetze-skateistan-sport-bildung-fuer-kinder/news/3917#ppp-sticky-anchor",
-};
+    'https://www.betterplace.org/de/projects/1114-unterstuetze-skateistan-sport-bildung-fuer-kinder/news/3917#ppp-sticky-anchor',
+}
 
 const expectedInitiative1: Initiative = {
-  city: "Berlin",
-  country: "Deutschland",
+  city: 'Berlin',
+  country: 'Deutschland',
   id: 1,
-  name: "Carrier 1",
+  name: 'Carrier 1',
   picture: [
     {
-      type: "fill",
+      type: 'fill',
       width: 100,
       height: 100,
       url:
-        "https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/000/045/fill_100x100_original_ARCHE_Logo_rgb_pos.jpg",
+        'https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/000/045/fill_100x100_original_ARCHE_Logo_rgb_pos.jpg',
     },
     {
-      type: "original",
+      type: 'original',
       url:
-        "https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/000/045/crop_original_original_ARCHE_Logo_rgb_pos.jpg",
+        'https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/000/045/crop_original_original_ARCHE_Logo_rgb_pos.jpg',
       width: null,
       height: null,
     },
   ],
-  url:
-    "https://www.betterplace.org/de/organisations/5147-berliner-obdachlosenhilfe-e-v",
-};
+  url: 'https://www.betterplace.org/de/organisations/5147-berliner-obdachlosenhilfe-e-v',
+}
 
 const expectedInitiative2: Initiative = {
-  city: "Berlin",
-  country: "Deutschland",
+  city: 'Berlin',
+  country: 'Deutschland',
   id: 2,
-  name: "Carrier 2",
+  name: 'Carrier 2',
   picture: [
     {
-      type: "fill",
+      type: 'fill',
       width: 100,
       height: 100,
       url:
-        "https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/025/417/fill_100x100_sea_watch_logo.png",
+        'https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/025/417/fill_100x100_sea_watch_logo.png',
     },
     {
-      type: "original",
+      type: 'original',
       url:
-        "https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/025/417/crop_original_sea_watch_logo.png",
+        'https://betterplace-assets.betterplace.org/uploads/organisation/profile_picture/000/025/417/crop_original_sea_watch_logo.png',
       width: null,
       height: null,
     },
   ],
-  url: "https://www.betterplace.org/de/organisations/25435-sea-eye-e-v",
-};
+  url: 'https://www.betterplace.org/de/organisations/25435-sea-eye-e-v',
+}
 
 const expectedProjects: Project[] = [
   {
     id: 1,
-    title: "Project 1",
-    summary: "Summary Project 1",
-    description: "Description Project 1",
-    city: "Kiew",
-    country: "Ukraine",
-    categories: ["education"],
+    title: 'Project 1',
+    summary: 'Summary Project 1',
+    description: 'Description Project 1',
+    city: 'Kiew',
+    country: 'Ukraine',
+    categories: ['education'],
     donationsCount: 42,
     progressPercentage: 33,
     openAmountInCents: 421234,
     picture: [
       {
-        type: "fill",
-        url: "https://www.example.com/image1_resized2.jpg",
+        type: 'fill',
+        url: 'https://www.example.com/image1_resized2.jpg',
         width: 100,
         height: 100,
       },
       {
-        type: "fill",
+        type: 'fill',
         width: 410,
         height: 214,
-        url: "https://www.example.com/image1_resized1.jpg",
+        url: 'https://www.example.com/image1_resized1.jpg',
       },
       {
-        type: "original",
-        url: "https://www.example.com/image1.jpg",
+        type: 'original',
+        url: 'https://www.example.com/image1.jpg',
         width: null,
         height: null,
       },
     ],
     initiative: expectedInitiative1,
-    donationUrl: "https://www.betterplace.org/de/donate/platform/projects/1",
-    newsUrl: "https://api.betterplace.org/de/api_v4/blog_posts/1.json",
+    donationUrl: 'https://www.betterplace.org/de/donate/platform/projects/1',
+    newsUrl: 'https://api.betterplace.org/de/api_v4/blog_posts/1.json',
     news: [expectedNews1, expectedNews2],
     newsCount: 2,
   },
   {
     id: 2,
-    title: "Project 2",
-    summary: "Summary Project 2",
-    description: "Description Project 2",
-    city: "Kiew",
-    country: "Ukraine",
-    categories: ["popular"],
+    title: 'Project 2',
+    summary: 'Summary Project 2',
+    description: 'Description Project 2',
+    city: 'Kiew',
+    country: 'Ukraine',
+    categories: ['popular'],
     donationsCount: 13,
     progressPercentage: 10,
     openAmountInCents: 1234567,
     picture: [],
     initiative: expectedInitiative1,
-    donationUrl: "https://www.betterplace.org/de/donate/platform/projects/2",
-    newsUrl: "https://api.betterplace.org/de/api_v4/blog_posts/2.json",
+    donationUrl: 'https://www.betterplace.org/de/donate/platform/projects/2',
+    newsUrl: 'https://api.betterplace.org/de/api_v4/blog_posts/2.json',
     news: [expectedNews1],
     newsCount: 1,
   },
   {
     id: 3,
-    title: "Project 3",
-    summary: "Summary Project 3",
-    description: "Description Project 3\n",
-    city: "Kiew",
+    title: 'Project 3',
+    summary: 'Summary Project 3',
+    description: 'Description Project 3\n',
+    city: 'Kiew',
     country: null,
-    categories: ["education", "popular"],
+    categories: ['education', 'popular'],
     donationsCount: 0,
     progressPercentage: 0,
     openAmountInCents: 4200000,
     picture: [],
     initiative: expectedInitiative2,
-    donationUrl: "https://www.betterplace.org/de/donate/platform/projects/3",
-    newsUrl: "https://api.betterplace.org/de/api_v4/blog_posts/3.json",
+    donationUrl: 'https://www.betterplace.org/de/donate/platform/projects/3',
+    newsUrl: 'https://api.betterplace.org/de/api_v4/blog_posts/3.json',
     news: [],
     newsCount: 0,
   },
   {
     id: 4,
-    title: "Project 4",
+    title: 'Project 4',
     summary: null,
     description: null,
     city: null,
-    country: "Ukraine",
-    categories: ["education", "popular"],
+    country: 'Ukraine',
+    categories: ['education', 'popular'],
     donationsCount: 0,
     progressPercentage: 0,
     openAmountInCents: 1200000,
     picture: [],
     initiative: expectedInitiative2,
-    donationUrl: "https://www.betterplace.org/de/donate/platform/projects/4",
-    newsUrl: "https://api.betterplace.org/de/api_v4/blog_posts/4.json",
+    donationUrl: 'https://www.betterplace.org/de/donate/platform/projects/4',
+    newsUrl: 'https://api.betterplace.org/de/api_v4/blog_posts/4.json',
     news: [],
     newsCount: 0,
   },
-];
+]
 
 export const expectedProjectsResponse: ProjectsResponse = {
   totalResults: 123,
   data: expectedProjects,
-};
+}
 
 export const expectedResult: Project = {
   id: 1,
-  title: "Project 1",
-  summary: "Summary Project 1",
-  description: "Description Project 1",
-  city: "Kiew",
-  country: "Ukraine",
-  categories: ["education"],
+  title: 'Project 1',
+  summary: 'Summary Project 1',
+  description: 'Description Project 1',
+  city: 'Kiew',
+  country: 'Ukraine',
+  categories: ['education'],
   donationsCount: 42,
   progressPercentage: 33,
   openAmountInCents: 421234,
   picture: [
     {
-      type: "fill",
-      url: "https://www.example.com/image1_resized2.jpg",
+      type: 'fill',
+      url: 'https://www.example.com/image1_resized2.jpg',
       width: 100,
       height: 100,
     },
     {
-      type: "fill",
+      type: 'fill',
       width: 410,
       height: 214,
-      url: "https://www.example.com/image1_resized1.jpg",
+      url: 'https://www.example.com/image1_resized1.jpg',
     },
     {
-      type: "original",
-      url: "https://www.example.com/image1.jpg",
+      type: 'original',
+      url: 'https://www.example.com/image1.jpg',
       width: null,
       height: null,
     },
   ],
   initiative: expectedInitiative1,
-  donationUrl: "https://www.betterplace.org/de/donate/platform/projects/1",
-  newsUrl: "https://api.betterplace.org/de/api_v4/blog_posts/1.json",
+  donationUrl: 'https://www.betterplace.org/de/donate/platform/projects/1',
+  newsUrl: 'https://api.betterplace.org/de/api_v4/blog_posts/1.json',
   news: [expectedNews1, expectedNews2],
   newsCount: 2,
-};
+}
diff --git a/app/common_test.ts b/app/common_test.ts
index 479fce8e98c033ec2224f46cc464f33538f3c7dc..ee4507da713d769430ffe200d6135eb8d08ce3e0 100644
--- a/app/common_test.ts
+++ b/app/common_test.ts
@@ -1,15 +1,15 @@
-import { returnsNext, stub } from "./dev_deps.ts";
-import { GraphQLServer } from "./server.ts";
+import { returnsNext, stub } from './dev_deps.ts'
+import { GraphQLServer } from './server.ts'
 
-export type ResponsePayload = Record<string, unknown> | Error;
+export type ResponsePayload = Record<string, unknown> | Error
 
 export const stubFetch = (response: ResponsePayload) => {
   return stub(
     globalThis,
-    "fetch",
+    'fetch',
     returnsNext([Promise.resolve(new Response(JSON.stringify(response)))]),
-  );
-};
+  )
+}
 
 export const processGqlRequest = (
   graphQLServer: GraphQLServer,
@@ -17,11 +17,11 @@ export const processGqlRequest = (
   variables: Record<string, unknown> = {},
   headers: Record<string, unknown> = {},
 ): Promise<Record<string, unknown> | undefined | null> => {
-  const request = new Request("http://localhost:8001/graphql", {
-    method: "POST",
+  const request = new Request('http://localhost:8001/graphql', {
+    method: 'POST',
     headers: {
-      "content-type": "application/json",
-      "accept": "*/*",
+      'content-type': 'application/json',
+      'accept': '*/*',
       ...headers,
     },
     body: JSON.stringify({
@@ -30,10 +30,10 @@ export const processGqlRequest = (
       query: query,
       extensions: { headers },
     }),
-  });
+  })
   return graphQLServer.handleRequest(request)
     // deno-lint-ignore no-explicit-any
     .then((response: any) => response.json())
     // deno-lint-ignore no-explicit-any
-    .then((response: any) => response.data);
-};
+    .then((response: any) => response.data)
+}
diff --git a/app/deps.ts b/app/deps.ts
index c41463b83ddbfbb2f20533698812e8a75ef59674..94270d824ada056f1fec3e1e95e32b52746fc158 100644
--- a/app/deps.ts
+++ b/app/deps.ts
@@ -1,5 +1,5 @@
-export { serve } from "https://deno.land/std@0.156.0/http/server.ts";
-export { createSchema, createYoga } from "npm:graphql-yoga@5.0.1";
-export { useResponseCache } from "npm:@graphql-yoga/plugin-response-cache@1.0.0";
-export { GraphQLError } from "npm:graphql@16.8.1";
-export { Parser } from "https://deno.land/x/html_parser@v0.1.3/src/mod.ts";
+export { serve } from 'https://deno.land/std@0.156.0/http/server.ts'
+export { createSchema, createYoga } from 'npm:graphql-yoga@5.0.1'
+export { useResponseCache } from 'npm:@graphql-yoga/plugin-response-cache@1.0.0'
+export { GraphQLError } from 'npm:graphql@16.8.1'
+export { Parser } from 'https://deno.land/x/html_parser@v0.1.3/src/mod.ts'
diff --git a/app/dev_deps.ts b/app/dev_deps.ts
index c3f570c4b1e7d7b0cabfc39a70bd95db3ea55cd9..cd82e58119121edb6283f04dad8164f79317c27a 100644
--- a/app/dev_deps.ts
+++ b/app/dev_deps.ts
@@ -1,18 +1,5 @@
-export {
-  assertSpyCall,
-  returnsNext,
-  stub,
-} from "https://deno.land/std@0.155.0/testing/mock.ts";
-export type { Stub } from "https://deno.land/std@0.155.0/testing/mock.ts";
-export {
-  assertEquals,
-  assertExists,
-  assertRejects,
-} from "https://deno.land/std@0.155.0/testing/asserts.ts";
-export {
-  afterEach,
-  beforeEach,
-  describe,
-  it,
-} from "https://deno.land/std@0.155.0/testing/bdd.ts";
-export { FakeTime } from "https://deno.land/std@0.198.0/testing/time.ts";
+export { assertSpyCall, returnsNext, stub } from 'https://deno.land/std@0.155.0/testing/mock.ts'
+export type { Stub } from 'https://deno.land/std@0.155.0/testing/mock.ts'
+export { assertEquals, assertExists, assertRejects } from 'https://deno.land/std@0.155.0/testing/asserts.ts'
+export { afterEach, beforeEach, describe, it } from 'https://deno.land/std@0.155.0/testing/bdd.ts'
+export { FakeTime } from 'https://deno.land/std@0.198.0/testing/time.ts'
diff --git a/app/logging.ts b/app/logging.ts
index 06779e533e520e78df05e7bb026dba44f13d747e..d9b19f3ef3958091c157f394bad4da9e8744f9d0 100644
--- a/app/logging.ts
+++ b/app/logging.ts
@@ -1,14 +1,14 @@
 // Google Cloud LogSeverity levels https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#logseverity
 export enum LogSeverity {
-  DEFAULT = "DEFAULT",
-  DEBUG = "DEBUG",
-  INFO = "INFO",
-  NOTICE = "NOTICE",
-  WARNING = "WARNING",
-  ERROR = "ERROR",
-  CRITICAL = "CRITICAL",
-  ALERT = "ALERT",
-  EMERGENCY = "EMERGENCY",
+  DEFAULT = 'DEFAULT',
+  DEBUG = 'DEBUG',
+  INFO = 'INFO',
+  NOTICE = 'NOTICE',
+  WARNING = 'WARNING',
+  ERROR = 'ERROR',
+  CRITICAL = 'CRITICAL',
+  ALERT = 'ALERT',
+  EMERGENCY = 'EMERGENCY',
 }
 
 const sortedLevels = [
@@ -21,20 +21,20 @@ const sortedLevels = [
   LogSeverity.CRITICAL,
   LogSeverity.ALERT,
   LogSeverity.EMERGENCY,
-];
+]
 
 /**
  * The Logger class requires a setUpLogger method to be run during the app's initialization in order get the current environment.
  */
 class Logger {
-  environment = "development";
+  environment = 'development'
 
   // minimum level to log
-  level = LogSeverity.DEFAULT;
+  level = LogSeverity.DEFAULT
 
   setUpLogger(environment: string, level: LogSeverity) {
-    this.environment = environment;
-    this.level = level;
+    this.environment = environment
+    this.level = level
   }
 
   /**
@@ -46,54 +46,52 @@ class Logger {
    * In other environments it should follow Google Cloud's Structured Logging formatting: https://cloud.google.com/logging/docs/structured-logging
    */
   log(severity: LogSeverity, message: string, options = {}) {
-    if (!shouldLogLevel(this.level, severity)) return;
+    if (!shouldLogLevel(this.level, severity)) return
 
-    const date = new Date().toISOString();
-    const input = this.environment === "development"
-      ? `${date} ${severity} ${message}`
-      : JSON.stringify({
-        environment: this.environment,
-        severity,
-        message,
-        ...options,
-      });
+    const date = new Date().toISOString()
+    const input = this.environment === 'development' ? `${date} ${severity} ${message}` : JSON.stringify({
+      environment: this.environment,
+      severity,
+      message,
+      ...options,
+    })
 
     switch (severity) {
       case LogSeverity.DEFAULT:
-        console.log(input);
-        break;
+        console.log(input)
+        break
       case LogSeverity.DEBUG:
-        console.debug(input);
-        break;
+        console.debug(input)
+        break
       case LogSeverity.INFO:
       case LogSeverity.NOTICE:
-        console.info(input);
-        break;
+        console.info(input)
+        break
       case LogSeverity.WARNING:
-        console.warn(input);
-        break;
+        console.warn(input)
+        break
       case LogSeverity.ERROR:
       case LogSeverity.CRITICAL:
       case LogSeverity.ALERT:
       case LogSeverity.EMERGENCY:
-        console.error(input);
+        console.error(input)
     }
   }
 
   debug(message: string, options = {}) {
-    this.log(LogSeverity.DEBUG, message, options);
+    this.log(LogSeverity.DEBUG, message, options)
   }
 
   info(message: string, options = {}) {
-    this.log(LogSeverity.INFO, message, options);
+    this.log(LogSeverity.INFO, message, options)
   }
 
   warn(message: string, options = {}) {
-    this.log(LogSeverity.WARNING, message, options);
+    this.log(LogSeverity.WARNING, message, options)
   }
 
   error(message: string, options = {}) {
-    this.log(LogSeverity.ERROR, message, options);
+    this.log(LogSeverity.ERROR, message, options)
   }
 }
 
@@ -103,9 +101,9 @@ class Logger {
  * @returns Boolean, true if the current level is accepted and false if it is rejected by the minLevel
  */
 const shouldLogLevel = (minLevel: LogSeverity, level: LogSeverity) => {
-  const minLevelIndex = sortedLevels.indexOf(minLevel);
-  const currentLevelIndex = sortedLevels.indexOf(level);
-  return currentLevelIndex >= minLevelIndex;
-};
+  const minLevelIndex = sortedLevels.indexOf(minLevel)
+  const currentLevelIndex = sortedLevels.indexOf(level)
+  return currentLevelIndex >= minLevelIndex
+}
 
-export const logger = new Logger();
+export const logger = new Logger()
diff --git a/app/main.ts b/app/main.ts
index e1292f81b7425faf050d9283d188283aec1e7a82..857fc522d0339d622e360baf3a4880f660611747 100644
--- a/app/main.ts
+++ b/app/main.ts
@@ -1,48 +1,43 @@
-import { logger, LogSeverity } from "./logging.ts";
-import {
-  DEFAULT_CACHE_ENABLED,
-  DEFAULT_CACHE_TTL_MS_BETTERPLACE,
-  DEFAULT_PORT,
-  startServer,
-} from "./server.ts";
+import { logger, LogSeverity } from './logging.ts'
+import { DEFAULT_CACHE_ENABLED, DEFAULT_CACHE_TTL_MS_BETTERPLACE, DEFAULT_PORT, startServer } from './server.ts'
 
-const environment = Deno.env.get("ENVIRONMENT") || "development";
+const environment = Deno.env.get('ENVIRONMENT') || 'development'
 
 logger.setUpLogger(
   environment,
-  environment === "development" ? LogSeverity.DEFAULT : LogSeverity.INFO,
-);
+  environment === 'development' ? LogSeverity.DEFAULT : LogSeverity.INFO,
+)
 
 const requiredEnv = <T>(
   name: string,
   typeFn: (s: string) => T,
   fallback?: T,
 ): T => {
-  const env = Deno.env.get(name);
+  const env = Deno.env.get(name)
   if (env === undefined && fallback === undefined) {
-    throw Error(`Environment variable "${name}" is required`);
+    throw Error(`Environment variable "${name}" is required`)
   } else {
-    return env !== undefined ? typeFn(env) : fallback!;
+    return env !== undefined ? typeFn(env) : fallback!
   }
-};
+}
 
-const asBoolean = (str: string) => /^true$/i.test(str);
+const asBoolean = (str: string) => /^true$/i.test(str)
 
 const serverConfigFromEnv = () => {
   return {
-    port: requiredEnv("PORT", Number, DEFAULT_PORT),
+    port: requiredEnv('PORT', Number, DEFAULT_PORT),
     cacheEnabled: requiredEnv(
-      "CACHE_ENABLED",
+      'CACHE_ENABLED',
       asBoolean,
       DEFAULT_CACHE_ENABLED,
     ),
     cacheTtlMsBetterplace: requiredEnv(
-      "CACHE_TTL_MS_BETTERPLACE",
+      'CACHE_TTL_MS_BETTERPLACE',
       Number,
       DEFAULT_CACHE_TTL_MS_BETTERPLACE,
     ),
-    fake: requiredEnv("FAKE", asBoolean, false), // For local development. If set, the API returns dummy data
-  };
-};
+    fake: requiredEnv('FAKE', asBoolean, false), // For local development. If set, the API returns dummy data
+  }
+}
 
-await startServer(serverConfigFromEnv());
+await startServer(serverConfigFromEnv())
diff --git a/app/server.ts b/app/server.ts
index ebc6f8470faad5bb3b8f5997e2a7cf76227a9edf..9f558d32471010fb05d36f8661701a72ba8434ff 100644
--- a/app/server.ts
+++ b/app/server.ts
@@ -7,7 +7,7 @@ import {
   ProjectParameters,
   ProjectsParameters,
   ProjectsResponse,
-} from "./types.ts";
+} from './types.ts'
 import {
   DEFAULT_LANGUAGE,
   fetchCategories,
@@ -16,9 +16,9 @@ import {
   fetchProject,
   fetchProjects,
   SUPPORTED_LANGUAGES,
-} from "./betterplace.ts";
-import { createSchema, createYoga, serve, useResponseCache } from "./deps.ts";
-import { logger } from "./logging.ts";
+} from './betterplace.ts'
+import { createSchema, createYoga, serve, useResponseCache } from './deps.ts'
+import { logger } from './logging.ts'
 
 const typeDefs = `
     type Picture {
@@ -80,17 +80,17 @@ const typeDefs = `
         projects(offset: Int = 0, limit: Int = 10, location: String): ProjectsResponse!
         project(id: Int!): Project!
     }
-`;
+`
 
 const fakeProject: Project = {
   id: 10,
-  title: "fake",
+  title: 'fake',
   categories: [],
   city: undefined,
   country: undefined,
   initiative: {
     id: 0,
-    name: "fake",
+    name: 'fake',
     city: undefined,
     country: undefined,
     picture: [],
@@ -101,11 +101,11 @@ const fakeProject: Project = {
   picture: [],
   summary: undefined,
   description: undefined,
-  donationUrl: "",
-  newsUrl: "",
+  donationUrl: '',
+  newsUrl: '',
   news: [],
   newsCount: 0,
-};
+}
 
 const createResolvers = (_config: ServerConfig) => ({
   Query: {
@@ -115,12 +115,10 @@ const createResolvers = (_config: ServerConfig) => ({
       parameters: ProjectsParameters = {},
       context: GraphQLContext,
     ): Promise<ProjectsResponse> =>
-      _config.fake
-        ? Promise.resolve({ totalResults: 0, data: [] })
-        : fetchProjects(
-          parameters,
-          getLanguage(context?.request?.headers),
-        ),
+      _config.fake ? Promise.resolve({ totalResults: 0, data: [] }) : fetchProjects(
+        parameters,
+        getLanguage(context?.request?.headers),
+      ),
     project: (
       // deno-lint-ignore no-explicit-any
       _parent: any,
@@ -133,8 +131,7 @@ const createResolvers = (_config: ServerConfig) => ({
       ),
   },
   Project: {
-    categories: (args: Project): Promise<string[]> =>
-      _config.fake ? Promise.resolve([]) : fetchCategories(args.id),
+    categories: (args: Project): Promise<string[]> => _config.fake ? Promise.resolve([]) : fetchCategories(args.id),
     news: (args: Project, parameters: NewsParameters = {}): Promise<News[]> =>
       _config.fake ? Promise.resolve([]) : fetchNews(args, parameters),
   },
@@ -142,29 +139,29 @@ const createResolvers = (_config: ServerConfig) => ({
     url: (args: Initiative): Promise<string | undefined> =>
       _config.fake ? Promise.resolve(undefined) : fetchInitiativeUrl(args),
   },
-});
+})
 
-export const DEFAULT_PORT = 8001;
-export const DEFAULT_CACHE_ENABLED = true;
-export const DEFAULT_CACHE_TTL_MS_BETTERPLACE = 60_000;
+export const DEFAULT_PORT = 8001
+export const DEFAULT_CACHE_ENABLED = true
+export const DEFAULT_CACHE_TTL_MS_BETTERPLACE = 60_000
 
 export interface ServerConfig {
-  port: number; // default: 8001
-  cacheEnabled: boolean; // default: true
-  cacheTtlMsBetterplace: number; // default: 60 seconds
-  fake: boolean; // For local development. If set, the API returns dummy data
+  port: number // default: 8001
+  cacheEnabled: boolean // default: true
+  cacheTtlMsBetterplace: number // default: 60 seconds
+  fake: boolean // For local development. If set, the API returns dummy data
 }
 
 const getLanguage = (headers?: Headers) => {
-  const languages: string = headers?.get("accept-language") || DEFAULT_LANGUAGE;
+  const languages: string = headers?.get('accept-language') || DEFAULT_LANGUAGE
   return (languages
-    .split(",") // languages are comma separated
-    .map((language) => language.split("-")[0]) // languages may include country code 'de-DE' e.g.
-    .map((language) => language.split(";")[0]) // languages may include a 'de;q=0.6' e.g.
+    .split(',') // languages are comma separated
+    .map((language) => language.split('-')[0]) // languages may include country code 'de-DE' e.g.
+    .map((language) => language.split(';')[0]) // languages may include a 'de;q=0.6' e.g.
     .map((language) => language.trim())
     .find((language) => SUPPORTED_LANGUAGES.includes(language)) ||
-    DEFAULT_LANGUAGE) as BetterPlaceLanguage;
-};
+    DEFAULT_LANGUAGE) as BetterPlaceLanguage
+}
 
 export const createGraphQLServer = (config: ServerConfig): GraphQLServer => {
   const plugins = config.cacheEnabled
@@ -173,49 +170,47 @@ export const createGraphQLServer = (config: ServerConfig): GraphQLServer => {
         // global cache per language, shared by all users
         session: (request: Request) => getLanguage(request.headers),
         ttlPerSchemaCoordinate: {
-          "Query.projects": config.cacheTtlMsBetterplace,
-          "Query.project": config.cacheTtlMsBetterplace,
+          'Query.projects': config.cacheTtlMsBetterplace,
+          'Query.project': config.cacheTtlMsBetterplace,
         },
       }),
     ]
-    : [];
-  const resolvers = createResolvers(config);
+    : []
+  const resolvers = createResolvers(config)
   return createYoga({
     schema: createSchema({ resolvers, typeDefs }),
     graphiql: true,
     plugins,
-  });
-};
+  })
+}
 
 // deno-lint-ignore no-explicit-any
-export type GraphQLServer = any;
+export type GraphQLServer = any
 
 type GraphQLContext = {
-  request?: { headers: Headers };
+  request?: { headers: Headers }
   params?: {
     extensions?: {
       headers?: {
-        [key: string]: string;
-      };
-    };
-  };
-};
+        [key: string]: string
+      }
+    }
+  }
+}
 
 export const startServer = (config: ServerConfig): Promise<void> => {
-  const graphQLServer: GraphQLServer = createGraphQLServer(config);
+  const graphQLServer: GraphQLServer = createGraphQLServer(config)
   return serve(graphQLServer, {
     port: config.port,
     onListen({ port, hostname }) {
       logger.info(
-        `Server started at http://${
-          hostname === "0.0.0.0" ? "localhost" : hostname
-        }:${port}/graphql`,
-      );
+        `Server started at http://${hostname === '0.0.0.0' ? 'localhost' : hostname}:${port}/graphql`,
+      )
       if (config.fake) {
         logger.info(
           `Server is serving fake data due to FAKE env var set to true`,
-        );
+        )
       }
     },
-  });
-};
+  })
+}
diff --git a/app/types.ts b/app/types.ts
index c333f6baf8133823bccd167bcb1ef847acbce05b..6d065810d51716f6736d0733e76b939b081cbebf 100644
--- a/app/types.ts
+++ b/app/types.ts
@@ -1,71 +1,71 @@
 export interface ProjectsParameters {
-  limit?: number;
-  offset?: number;
-  location?: string;
+  limit?: number
+  offset?: number
+  location?: string
 }
 
 export interface ProjectParameters {
-  id: number;
+  id: number
 }
 
 export interface Picture {
-  url: string;
-  type: string;
-  width?: number | null;
-  height?: number | null;
+  url: string
+  type: string
+  width?: number | null
+  height?: number | null
 }
 
 export interface Initiative {
-  id: number;
-  name: string;
-  city: string | undefined | null;
-  country: string | undefined | null;
-  picture: Picture[];
-  url?: string;
+  id: number
+  name: string
+  city: string | undefined | null
+  country: string | undefined | null
+  picture: Picture[]
+  url?: string
 }
 
 export interface Author {
-  name: string;
-  picture: Picture[];
+  name: string
+  picture: Picture[]
 }
 
 export interface News {
-  id: number;
-  title: string;
-  publishDate: string;
-  author?: Author | null;
-  body: string;
-  url: string;
+  id: number
+  title: string
+  publishDate: string
+  author?: Author | null
+  body: string
+  url: string
 }
 
 export interface NewsParameters {
-  limit?: number;
+  limit?: number
 }
 
 export interface Project {
-  id: number;
-  title: string;
-  categories: string[];
-  city: string | undefined | null;
-  country: string | undefined | null;
-  initiative: Initiative;
-  donationsCount: number;
+  id: number
+  title: string
+  categories: string[]
+  city: string | undefined | null
+  country: string | undefined | null
+  initiative: Initiative
+  donationsCount: number
   /** Number between 0 and 100 */
-  progressPercentage: number;
-  openAmountInCents: number;
+  progressPercentage: number
+  openAmountInCents: number
   /** The project's "profile picture" in different variants */
-  picture: Picture[];
-  summary: string | undefined | null;
-  description: string | undefined | null;
-  donationUrl: string;
-  newsUrl: string;
-  news: News[];
-  newsCount: number;
+  picture: Picture[]
+  summary: string | undefined | null
+  description: string | undefined | null
+  donationUrl: string
+  newsUrl: string
+  news: News[]
+  newsCount: number
 }
 
 export interface ProjectsResponse {
-  totalResults: number;
-  data: Project[];
+  totalResults: number
+  data: Project[]
 }
 
-export type BetterPlaceLanguage = "de" | "en";
+export type BetterPlaceLanguage = 'de' | 'en'
diff --git a/deno.json b/deno.json
index 23a254d9873989eb74c5c4c5b8501024f6451208..4ffff98c81635a268f7ae97151213f6335534e3a 100644
--- a/deno.json
+++ b/deno.json
@@ -19,6 +19,9 @@
     }
   },
   "fmt": {
+    "lineWidth": 120,
+    "singleQuote": true,
+    "semiColons": false,
     "exclude": [
       "*.md"
     ]
diff --git a/terraform/environments/scripts/destroy-env.sh b/terraform/environments/scripts/destroy-env.sh
index d8137694745e9a6bcded13142bf6a5e666b55e6c..aac6dea64eafc13c326e5b4819351c32365e9b3c 100755
--- a/terraform/environments/scripts/destroy-env.sh
+++ b/terraform/environments/scripts/destroy-env.sh
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
 
 # exit when any command fails
 set -ex
@@ -12,7 +12,7 @@ export TF_LOG=DEBUG
 # * GCP stuff not allowing our resources to be deleted.
 # Most of the time, retrying a destroy fixes these causes.
 retry() {
-  for i in {1..3}; do
+  for i in $(seq 1 3); do
     set +e
     "$@"
     retval=$?