4coders.net dev tools
While having some time for research and keeping up with tech development, I decided to bootstrap a small website for developer tools.
The idea is to have a collection of helpful and widely used developer tools. I started with implementing a base64 encoding/decoding and QR code generation functionality. Not very innovative at this point, but it's just the start ;) More things will follow.
The backend architecture is based on AWS serverless functions written in Rust and compiled to binary to have maximum performance and efficiency.
Frontend is written in SvelteKit.
Including domain registration, DNS setup, backend infrastructure, implementation of Rust functions for base64 encoding/decoding, frontend bootstrapping and implementation, mobile view, styling, basic SEO setup, I was able to launch the MVP within a day.
To support code reviews and security audits, I received AI support from Claude 3.5 Sonnet ;)
I will update this post while things progress.
Refactoring dcshangar.com
- Next.js App Router
- React Server Components
Launching dcshangar.com
New Project: dcshangar.com for sharing community content for DCS World.
Features and frameworks
- multipart upload of screenshots and files
- download with temporary signed urls
- auto thumbnail and zip generation
- auto language detection of text content
- auto virus check of uploaded files
- parsing of mission files display of details
- search and filter settings
- comments
- authentication
- dark mode
- slack & discord link unfurling
- websockets for push based client messaging
- optional short URLs (dcs.rocks) for sharing
Tech Stack
- react + nextjs 12 deployed via Vercel
- AWS backend (nodejs, typescript, serverless, aws cdk, 30+ stacks)
- slack integration for alarming und notifications
- continuous integration via github actions and Vercel
- E2E testing with playwright and Saucelabs Cloud
React Simple Side Effects
https://github.com/christiangoetze/react-simple-side-effects
beforeDispatch(Actions.MY_ACTION_1, () => { // do some stuff before state changed }); afterDispatch(Actions.MY_ACTION_1, () => { // do some stuff after state changed }); afterDispatch<Action1, AppState>(Actions.MY_ACTION_1, ({action, oldState, newState}) => { // access action or state console.log(action.payload, oldState, newState); }); afterDispatch(Actions.MY_ACTION_1, ({dispatch}) => { // dispatch a new action dispatch(action2()); });
Launching hotlap.gg
After some development time, one of my side projects is now going live. hotlap.gg – Sim racing setups
A web app that offers setups for various sim racing games.
Currently reduced to Project Cars 2 and basic functions such as create and search, many features will follow in the next few months.
PageSpeed :P
After some optimizations, the results are quite satifying.
Thx @aws and @angular
Hosting Angular on AWS S3 (using a Strato domain) + ci
Amazon Webservices offers a great option for cheap and ultra fast hosting of a single page app like angular.
Setup AWS S3
- Create a S3 bucket
- Enable static website hosting (properties tab in your bucket). Enter index.html as your index and error document.
- In Permissions->Bucket Policy allow public read access. Insert the following policy inside the statement array of the policy json:
{ "Sid": "1", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME_HERE/*" }
Setup AWS Cloudfront
- create a new web distribution
- enter your alternate domain names (e.g. cgoetze.de and www.cgoetze.de, one per line)
- default root object: index.html
- leave everything else on default
- once it is created navigate to the origins tab and create a new origin
- choose your s3 bucket as origin domain name
- for this tutorial leave 'Restrict Bucket Access' to No, save and exit
- navigate to the behaviors tab and create a new behavior
- leave the path pattern to default(*)
- select the origin we just created, save and exit
- navigate to the errors tab and create a custom error response. This is a kind of workaroud to map all paths to the index.html
- select 404: Not Found and select Yes for the customize error response checkbox. Insert /index.html as the response page path and set the status code to 200: OK.
Setup AWS Route53
To map your strato domain to your amazon cloudfront cache, perform the following steps:
- create a new public hosted zone
- NS-Name Server and SOA records should be created automatically
- additionally create an A - IPv4 address record for each domain you want to map
- enter yourdomain.com as name, for the second A record you may enter www.yourdomain.com
- enable the Alias checkbox and select Yes
- the alias target should be your cloudfront url (e.g. xyz123.cloudfront.net.) With a trailing dot.
- select routing policy Simple
Setup Strato DNS record
- redirect your domain to the www. subdomain. (e.g. cgoetze.de is redirected to www.cgoetze.de with external http redirection)
- open the dns management of your www subdomain
- add a new ns record and insert all four route 53 name servers which are display in the ns record we created in route 53. Insert them with the trailing dot at the end.
- apply the changes and thats it for the most complicated part of this tutorial
- be aware that dns changes of strato and route53 can take some time before they are distributed across all parties
Setup Angular project
- create the following buildspec.yml file in the top level directory of your angular cli project
version: 0.2 env: variables: S3_BUCKET: "YOUR_BUCKET_NAME_HERE" <- only the bucket name, not the full path phases: install: commands: - npm i build: commands: - npm run build-prod post_build: commands: - aws s3 cp dist s3://${S3_BUCKET} --recursive artifacts: files: - '**/*' base-directory: 'dist'
- note the build-prod script under build->commands of the buildspec file. This a script i defined in my package.json which basically executes ng build --prod
Setup CI with AWS Codebuild
- create a new aws code build project
- for angular i choose the nodejs 7 image
- as artifact type choose No Artifacts. Because you want to copy the files to the s3 bucket top level directory as defined in the buildspec.yml, we don't need to define an artifact here. If you select folder, then we will end up with a subfolder in our s3 bucket which will cause us some problems when using the static site hosting.
Creating a simple Angular contentful service
Now we're going to create a simple angular service to fetch data from contentfuls api.
First, let's create a contentful.service.ts
import { Injectable } from '@angular/core'; import { Observable, from } from 'rxjs'; import * as contentful from 'contentful'; import { ContentfulEntries } from './contentful-entries.model'; @Injectable() export class ContentfulService { private readonly client: any; constructor() { this.client = contentful.createClient({ space: '...', accessToken: '...' }); } getAllEntriesByContentType(contentType: string): Observable<ContentfulEntries> { return from(this.client.getEntries({ content_type: contentType }) as Promise<ContentfulEntries>); } }
When querying the contentful entries endpoint we get the following response.
Notice: Everything inside "fields" is custom content model structure.
(I removed nonrelevant parts)
{ ... "items": [ { "sys": { ..., "updatedAt": "2017-02-05T09:00:39.151Z", ... }, "fields": { "title": "Creating a simple Angular2 contentful service", "text": ..., "image": ..., "authors": [ "Christian" ], "tags": [ "contentful", "angular2", "typescript" ] } } ], "includes": { ... } }
To work with this response, let's create some models the angular way;
contentful-entries.model.ts
import { ContentfulItem, ContentfulInclude } from './'; export class ContentfulEntries { items: ContentfulItem[]; includes: ContentfulInclude[]; }
contentful-item.model.ts
export class ContentfulItem { sys: any; fields: any; }