Removed S3
This commit is contained in:
parent
c0923aaf2b
commit
2edff6915a
15 changed files with 51 additions and 203 deletions
|
@ -71,8 +71,5 @@ So, up to this point, you may have been thinking: "Gee Atri... you can't do anyt
|
||||||
|
|
||||||
With Go managing route handlers and API routes, the template language running the UI, and HTMX governing interactivity on the front end, you can effectively write a fully dynamic full-stack application without writing a line of JavaScript code. It even runs quite a bit faster than some of the JS world's frameworks (Astro, for instance). It is actually what powers this site right now! The fundamentals are essential here and come together for a clean and enjoyable developer experience. I encourage everyone in the JS world to give it a shot! Perhaps it is not your thing, and that's okay! But you might also just fall in love with it!
|
With Go managing route handlers and API routes, the template language running the UI, and HTMX governing interactivity on the front end, you can effectively write a fully dynamic full-stack application without writing a line of JavaScript code. It even runs quite a bit faster than some of the JS world's frameworks (Astro, for instance). It is actually what powers this site right now! The fundamentals are essential here and come together for a clean and enjoyable developer experience. I encourage everyone in the JS world to give it a shot! Perhaps it is not your thing, and that's okay! But you might also just fall in love with it!
|
||||||
|
|
||||||
# Giving It A Shot
|
|
||||||
I have a [repository](https://github.com/atridadl/goth.stack) as well as a [demo](https://goth-stack.fly.dev/) ready to go with everything you need to start!
|
|
||||||
|
|
||||||
# Thanks!
|
# Thanks!
|
||||||
If you found this helpful, please let me know by email at [me@atri.dad](mailto:me@atri.dad). Until next time!
|
If you found this helpful, please let me know by email at [me@atri.dad](mailto:me@atri.dad). Until next time!
|
10
go.mod
10
go.mod
|
@ -12,9 +12,9 @@ require (
|
||||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||||
golang.org/x/image v0.19.0 // indirect
|
golang.org/x/image v0.20.0 // indirect
|
||||||
golang.org/x/net v0.28.0 // indirect
|
golang.org/x/net v0.29.0 // indirect
|
||||||
golang.org/x/text v0.17.0 // indirect
|
golang.org/x/text v0.18.0 // indirect
|
||||||
golang.org/x/time v0.6.0 // indirect
|
golang.org/x/time v0.6.0 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||||
)
|
)
|
||||||
|
@ -30,7 +30,7 @@ require (
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/yuin/goldmark v1.7.4
|
github.com/yuin/goldmark v1.7.4
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||||
golang.org/x/crypto v0.26.0 // indirect
|
golang.org/x/crypto v0.27.0 // indirect
|
||||||
golang.org/x/sys v0.24.0 // indirect
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -63,18 +63,28 @@ github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
||||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||||
|
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||||
|
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/image v0.19.0 h1:D9FX4QWkLfkeqaC62SonffIIuYdOk/UE2XKUBgRIBIQ=
|
golang.org/x/image v0.19.0 h1:D9FX4QWkLfkeqaC62SonffIIuYdOk/UE2XKUBgRIBIQ=
|
||||||
golang.org/x/image v0.19.0/go.mod h1:y0zrRqlQRWQ5PXaYCOMLTW2fpsxZ8Qh9I/ohnInJEys=
|
golang.org/x/image v0.19.0/go.mod h1:y0zrRqlQRWQ5PXaYCOMLTW2fpsxZ8Qh9I/ohnInJEys=
|
||||||
|
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
|
||||||
|
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
|
||||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||||
|
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||||
|
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
|
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||||
|
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|
33
lib/files.go
Normal file
33
lib/files.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package lib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListFiles returns a slice of file paths in the given directory
|
||||||
|
func ListFiles(dir string) ([]string, error) {
|
||||||
|
var filePaths []string
|
||||||
|
|
||||||
|
entries, err := os.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range entries {
|
||||||
|
if entry.IsDir() {
|
||||||
|
// Recursively list files in subdirectories
|
||||||
|
subDir := filepath.Join(dir, entry.Name())
|
||||||
|
subFiles, err := ListFiles(subDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
filePaths = append(filePaths, subFiles...)
|
||||||
|
} else {
|
||||||
|
// Add file path to the slice
|
||||||
|
filePath := filepath.Join(dir, entry.Name())
|
||||||
|
filePaths = append(filePaths, filePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filePaths, nil
|
||||||
|
}
|
125
lib/s3.go
125
lib/s3.go
|
@ -1,125 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
|
||||||
"github.com/aws/aws-sdk-go/service/s3"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Generates a presigned URL for the given key. Returns the pre-signed URL.
|
|
||||||
func GeneratePublicURL(key string) string {
|
|
||||||
// Get the S3 bucket name
|
|
||||||
bucket := os.Getenv("BUCKET_NAME")
|
|
||||||
if bucket == "" {
|
|
||||||
fmt.Println("No S3 bucket specified.")
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the S3 session
|
|
||||||
endpoint := os.Getenv("AWS_ENDPOINT_URL_S3")
|
|
||||||
accessKeyID := os.Getenv("AWS_ACCESS_KEY_ID")
|
|
||||||
secretAccessKey := os.Getenv("AWS_SECRET_ACCESS_KEY")
|
|
||||||
region := os.Getenv("AWS_REGION")
|
|
||||||
|
|
||||||
sess, err := session.NewSession(&aws.Config{
|
|
||||||
Region: ®ion,
|
|
||||||
Credentials: credentials.NewStaticCredentials(
|
|
||||||
accessKeyID,
|
|
||||||
secretAccessKey,
|
|
||||||
"",
|
|
||||||
),
|
|
||||||
Endpoint: aws.String(endpoint),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
svc := s3.New(sess)
|
|
||||||
|
|
||||||
// Generate the presigned URL
|
|
||||||
req, _ := svc.GetObjectRequest(&s3.GetObjectInput{
|
|
||||||
Bucket: &bucket,
|
|
||||||
Key: &key,
|
|
||||||
})
|
|
||||||
urlStr, err := req.Presign(15 * time.Minute)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return urlStr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generates a list of presigned URLs for all items in the given directory. Returns an array of pre-signed URLs.
|
|
||||||
func GeneratePublicURLsFromDirectory(directory string) []string {
|
|
||||||
// Get the S3 bucket name
|
|
||||||
bucket := os.Getenv("BUCKET_NAME")
|
|
||||||
if bucket == "" {
|
|
||||||
fmt.Println("No S3 bucket specified.")
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the S3 session
|
|
||||||
endpoint := os.Getenv("AWS_ENDPOINT_URL_S3")
|
|
||||||
accessKeyID := os.Getenv("AWS_ACCESS_KEY_ID")
|
|
||||||
secretAccessKey := os.Getenv("AWS_SECRET_ACCESS_KEY")
|
|
||||||
region := os.Getenv("AWS_REGION")
|
|
||||||
|
|
||||||
sess, err := session.NewSession(&aws.Config{
|
|
||||||
Region: ®ion,
|
|
||||||
Credentials: credentials.NewStaticCredentials(
|
|
||||||
accessKeyID,
|
|
||||||
secretAccessKey,
|
|
||||||
"",
|
|
||||||
),
|
|
||||||
Endpoint: aws.String(endpoint),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
svc := s3.New(sess)
|
|
||||||
|
|
||||||
// Create the input for the ListObjectsV2 call
|
|
||||||
input := &s3.ListObjectsV2Input{
|
|
||||||
Bucket: aws.String(bucket),
|
|
||||||
Prefix: aws.String(directory),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the list of items in the directory
|
|
||||||
result, err := svc.ListObjectsV2(input)
|
|
||||||
if err != nil {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Remove the items in results that are directories
|
|
||||||
for i := 0; i < len(result.Contents); i++ {
|
|
||||||
if *result.Contents[i].Key == directory {
|
|
||||||
result.Contents = append(result.Contents[:i], result.Contents[i+1:]...)
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the presigned URLs
|
|
||||||
urls := []string{}
|
|
||||||
for _, item := range result.Contents {
|
|
||||||
req, _ := svc.GetObjectRequest(&s3.GetObjectInput{
|
|
||||||
Bucket: aws.String(bucket),
|
|
||||||
Key: item.Key,
|
|
||||||
})
|
|
||||||
urlStr, err := req.Presign(15 * time.Minute)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
urls = append(urls, urlStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return urls
|
|
||||||
}
|
|
1
main.go
1
main.go
|
@ -44,7 +44,6 @@ func main() {
|
||||||
e.GET("/", pages.Home)
|
e.GET("/", pages.Home)
|
||||||
e.GET("/projects", pages.Projects)
|
e.GET("/projects", pages.Projects)
|
||||||
e.GET("/talks", pages.Talks)
|
e.GET("/talks", pages.Talks)
|
||||||
e.GET("/testimonials", pages.Testimonials)
|
|
||||||
e.GET("/posts", pages.Posts)
|
e.GET("/posts", pages.Posts)
|
||||||
e.GET("/posts/:post", pages.Post)
|
e.GET("/posts/:post", pages.Post)
|
||||||
e.GET("/tools", pages.Tools)
|
e.GET("/tools", pages.Tools)
|
||||||
|
|
|
@ -100,14 +100,9 @@ func Home(c echo.Context) error {
|
||||||
buttons := []lib.ButtonLink{
|
buttons := []lib.ButtonLink{
|
||||||
{
|
{
|
||||||
Name: "Resumé",
|
Name: "Resumé",
|
||||||
Href: lib.GeneratePublicURL("Atridad_Lahiji_Resume.pdf"),
|
Href: "/public/files/Atridad_Lahiji_Resume.pdf",
|
||||||
Internal: false,
|
Internal: false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "Testimonials",
|
|
||||||
Href: "/testimonials",
|
|
||||||
Internal: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: "Posts",
|
Name: "Posts",
|
||||||
Href: "/posts",
|
Href: "/posts",
|
||||||
|
|
|
@ -21,7 +21,7 @@ func Talks(c echo.Context) error {
|
||||||
{
|
{
|
||||||
Name: "Hypermedia as the engine of application state - an Introduction",
|
Name: "Hypermedia as the engine of application state - an Introduction",
|
||||||
Description: "A talk on building reactive websites using tools like HTMX instead of JSON + JS. Will be presented at the Dev Edmonton Fabruary 2024 JS/Ruby/Python Meetup",
|
Description: "A talk on building reactive websites using tools like HTMX instead of JSON + JS. Will be presented at the Dev Edmonton Fabruary 2024 JS/Ruby/Python Meetup",
|
||||||
Href: lib.GeneratePublicURL("hypermedia_talk_atridad.pdf"),
|
Href: "/public/files/hypermedia_talk_atridad.pdf",
|
||||||
Tags: []string{"golang", "htmx", "ssr"},
|
Tags: []string{"golang", "htmx", "ssr"},
|
||||||
Date: "February 01, 2024",
|
Date: "February 01, 2024",
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,11 +14,6 @@
|
||||||
Talks
|
Talks
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<a class="no-underline" href="/testimonials">
|
|
||||||
Testimonials
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<a class="no-underline" href="/tools">
|
<a class="no-underline" href="/tools">
|
||||||
Tools
|
Tools
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
{{define "title"}}
|
|
||||||
Atridad Lahiji // Testimonials
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{define "headercontent"}}
|
|
||||||
Atridad Lahiji // Testimonials
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{define "head"}}
|
|
||||||
<link rel="stylesheet" href="/public/css/styles.css" />
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{define "main"}}
|
|
||||||
<h2 class="text-2xl font-extrabold tracking-tight text-white sm:text-[2rem]">
|
|
||||||
What <a class="link link-secondary"
|
|
||||||
href="https://steamcommunity.com/app/1230140/reviews/?browsefilter=toprated&snr=1_5_100010_" target="_blank"
|
|
||||||
rel="noreferrer">People</a> Say About Me
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3">
|
|
||||||
{{range .Images}}
|
|
||||||
<div>
|
|
||||||
<img class="object-cover object-center w-full max-w-full rounded-lg" src={{.}} alt="Review of Atri"
|
|
||||||
loading="lazy" />
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{define "foot"}}
|
|
||||||
{{end}}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package pages
|
|
||||||
|
|
||||||
import (
|
|
||||||
"atri.dad/lib"
|
|
||||||
"github.com/labstack/echo/v4"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TestimonialsProps struct {
|
|
||||||
Images []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func Testimonials(c echo.Context) error {
|
|
||||||
images := lib.GeneratePublicURLsFromDirectory("testimonials/")
|
|
||||||
|
|
||||||
props := TestimonialsProps{
|
|
||||||
Images: images,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specify the partials used by this page
|
|
||||||
partials := []string{"header", "navitems"}
|
|
||||||
|
|
||||||
// Render the template
|
|
||||||
return lib.RenderTemplate(c.Response().Writer, "base", partials, props)
|
|
||||||
}
|
|
|
@ -21,7 +21,7 @@ func Resize(c echo.Context) error {
|
||||||
{
|
{
|
||||||
Name: "Hypermedia as the engine of application state - an Introduction",
|
Name: "Hypermedia as the engine of application state - an Introduction",
|
||||||
Description: "A talk on building reactive websites using tools like HTMX instead of JSON + JS. Will be presented at the Dev Edmonton Fabruary 2024 JS/Ruby/Python Meetup",
|
Description: "A talk on building reactive websites using tools like HTMX instead of JSON + JS. Will be presented at the Dev Edmonton Fabruary 2024 JS/Ruby/Python Meetup",
|
||||||
Href: lib.GeneratePublicURL("hypermedia_talk_atridad.pdf"),
|
// Href: lib.GeneratePublicURL("hypermedia_talk_atridad.pdf"),
|
||||||
Tags: []string{"golang", "htmx", "ssr"},
|
Tags: []string{"golang", "htmx", "ssr"},
|
||||||
Date: "February 01, 2024",
|
Date: "February 01, 2024",
|
||||||
},
|
},
|
||||||
|
|
BIN
public/files/Atridad_Lahiji_Resume.pdf
Normal file
BIN
public/files/Atridad_Lahiji_Resume.pdf
Normal file
Binary file not shown.
BIN
public/files/hypermedia_talk_atridad.pdf
Normal file
BIN
public/files/hypermedia_talk_atridad.pdf
Normal file
Binary file not shown.
BIN
public/img/articles/scalability.png
Normal file
BIN
public/img/articles/scalability.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 145 KiB |
Loading…
Add table
Reference in a new issue